I am currently writing some acceptance tests to a jersey 2-0 webservice (json) before refactoring some methods in the project, and i have stumbled upon a problem with asserting blank-space strings from the webservice.
I get the following output from my webservice:
"Boxes": [
{
"id": 1,
"title": " ", //Yes this is a white-space
"genre": "genre",
"info": "some info",
"rating": "3",
"artist": "Artist 1"
}
],
And i convert my response to JSONObject from the webservice as following:
public static JSONObject responseToJsonObject(HttpResponse httpResponse) throws IOException {
String responseString = EntityUtils.toString(httpResponse.getEntity(), "UTF-8");
return new JSONObject(responseString);
}
Then in my test, is do normal asserts like so:
//* http request creation omitted *//
JSONObject jsonResponse = JsonTranslator.responseToJsonObject(httpRequest)
JSONArray boxes = jsonResponse.getJSONArray("boxes ");
JSONObject result = boxes .getJSONObject(0);
assertEquals(" ", result.getString("title"));
Problem is that this last assert fails.
org.junit.ComparisonFailure:
Expected :
Actual :
And i probably know why, the byte arrays yield two different results. One has a byte of [32] (the one created in java) and the one from the webservice has [-62,-96]
I have never encountered this problem before. And if i try to convert without the "UTF-8" in the EntityUtils method i get an even worse result (Â byte array: [-61,-126,-62,-96]
I can see my webservice's content-type header is properly set as application/json
Can anyone explain what happens here?
The character you are getting there is not a "normal" space. It's a no-break space. The same character that in HTML would be described with .
Its unicode value is '\u00A0'. Its UTF-8 representation is C2 A0, which is what you are getting in your byte array.
I believe if you tried the following assert it would work:
assertEquals("\u00A0", result.getString("title"));
Related
I'm working on a test suite for some Java code that uses jsonpatch to modify db entries. What I am trying to do is have a template jsonpatch request saved down as a file that individual unit tests could read from, modify some operations, and then call the patch directly.
The rough structure is as follows:
jsonpatch template:
"jsonPatch": [
{
"op": "replace",
"path": "/username",
"value": "johnDoe"
},
{
"op": "replace",
"path": "/number",
"value": 123
}
]
java code:
// Import Template
JsonPatch request;
InputStream is = TestRestTemplate.class.getResourceAsStream("/PatchRequest.json");
request = objectMapper.readValue(is, JsonPatch.class)
// Modify Operations (not working)
Random r = new Random();
int newNumber = r.nextInt(100);
((ObjectNode) request).put("/number", newNumber); // this doesn't even compile due to conversion issues
// Send patch
thingThatTouchesDB.patchDocument(request)
// Validate Results
int finalNumber = [get field from DB]
assertEquals(newNumber, finalNumber);
When I comment out the modify operation section everything works so I'm not having issues with importing or sending the patch. My struggle is with updating the template's operations to fit. The paths are the same across tests but I need to try with different values each time since we're using a persistent database for testing.
Is there a way to modify the value of an existing jsonpatch operation like I'm trying above? Failing that, can I add new operations to the existing jsonpatch?
After a lot of trial and error I got it to work by modifying the inputstream itself instead of the jsonpatch object.
I added some targets to the json template and did stream replacement on a copy of the inputstream to force in my desired values before converting it all into the final jsonpatch.
new template:
"jsonPatch": [
{
"op": "replace",
"path": "/username",
"value": "$username$"
},
{
"op": "replace",
"path": "/number",
"value": "$number$"
}
]
new code:
// Import Template
JsonPatch request;
InputStream is = TestRestTemplate.class.getResourceAsStream("/PatchRequest.json");
byte[] bytes = FileCopyUtils.copyToByteArray(is);
String requestStr= new String(bytes);
// Modify Operations
Random r = new Random();
int newNumber = r.nextInt(100);
requestStr= requestStr.replaceAll("\"\\$number\\$\"", String.valueOf(newNumber));
requestStr= requestStr.replaceAll("\\$username\\$", "NewName");
// Finalize Request
request = objectMapper.readValue(requestStr, JsonPatch.class)
Getting the number value to work was a bit tricky since everything is strings, but I was able to crack it by having the replace operation get rid of its quotes which causes it to get picked up as a number by the jsonpatch.
I am new in Java coding, I am trying to post a JSOn file, here is my JSON file object
{
"report": "[{\"patientId\":\"abcd-efg\",\"campaignId\":\"2\",\"phoneCallsMade\":\"[]\",\"message\":\"[]\"}, {\"patientId\":\"abcd-efg\",\"campaignId\":\"2\",\"phoneCallsMade\":\"[]\",\"message\":\"[]\"}]"
}
I am trying to remove the backslash, I tried below methods :
myJsonString.replaceAll("\\","");
myJsonString=myJsonString.replaceAll("\\\\","");
but after doing that the json format is not valid. Can someone help me please.
This is just a string not a json array. And the reason of getting invalid json post removing slashes is due to in correct mapping of double quotes. Just remove double quotes from "[ & ]" from beginning and from end and perform the operation. Your problem will be resolved.
{
"report": [{
"patientId": "abcd-efg",
"campaignId": "2",
"phoneCallsMade": "[]",
"message": "[]"
}, {
"patientId": "abcd-efg",
"campaignId": "2",
"phoneCallsMade": "[]",
"message": "[]"
}]
}
This will be the output.
I am trying to create gists in Github via REST ASSURED.
To create a gist a need to pass file names and their contents.
Now, the content of the file is something which is being rejected by the API.
Example:
{
"description": "Hello World Examples",
"public": true,
"files": {
"hello_world.rb": {
"content": "class HelloWorld\n def initialize(name)\n #name = name.capitalize\n end\n def sayHi\n puts \"Hello !\"\n end\nend\n\nhello = HelloWorld.new(\"World\")\nhello.sayHi"
},
"hello_world.py": {
"content": "class HelloWorld:\n\n def init(self, name):\n self.name = name.capitalize()\n \n def sayHi(self):\n print \"Hello \" + self.name + \"!\"\n\nhello = HelloWorld(\"world\")\nhello.sayHi()"
},
"hello_world_ruby.txt": {
"content": "Run ruby hello_world.rb to print Hello World"
},
"hello_world_python.txt": {
"content": "Run python hello_world.py to print Hello World"
}
}
This is how the the API wants the JSON to be, I could get this via my code:
{
"description": "Happy World",
"public": true,
"files": {
"sid.java": {
"content": "Ce4z5e22ta"
},
"siddharth.py": {
"content": "def a:
if sidh>kundu:
sid==kundu
else:
kundu==sid
"
}
}
}
So the change in the indentations is causing GitHUb API to fail this with 400 error. Can someone please help?
As pointed out in the comments, JSON does not allow control characters in strings. In the case of line breaks, these were encoded as \n in the example.
You should definitely consider using a proper library to create the JSON rather than handling the raw strings yourself.
Create a POJO which will represent your gist (i.e. object with fields like 'description', 'files' collection. And separate POJO for file containing string fields 'name' and 'content';
Do something like this to convert your gist:
try {
GistFile file new GistFile();// Assuming this is POJO for your file
//Set name and content
Gist gist = new Gist(); //Asuming this is a POJO for your gist
gist.addFile(file);
//Add more files if needed and set other properties
ObjectMapper mapper = new ObjectMapper();
String content = mapper.writeValueAsString(gist);
//Now you have valid JSON string
} catch (Exception e) {
e.printStackTrace();
}
This is for com.fasterxml.jackson.databind.ObjectMapper or use different JSON library
Actually there are GitHub specific libraries which do most of the job for you. Please refer to this question: How to connect to github using Java Program it might be helpful
I am working on a module where i am getting a JSON response from a RESTful web service. The response is something like below.
[{
"orderNumber": "test order",
"orderDate": "2016 - 01 - 25",
"Billing": {
"Name": "Ron",
"Address": {
"Address1": "",
"City": ""
}
},
"Shipping": {
"Name": "Ron",
"Address": {
"Address1": "",
"City": ""
}
}
}]
This is not the complete response, but only with important elements just to elaborate the issue.
So what i need to do is, convert this JSON response into another JSON that my application understands and can process. Say the below for example.
{
"order_number": "test order",
"order_date": "2016-01-25",
"bill_to_name": "Ron",
"bill_to_address": "",
"bill_to_city": "",
"ship_from_name": "Ron",
"ship_from_Address": "",
"ship_from_city": ""
}
The idea that i had tried was to convert the JSONObject in the response i receive to a hashmap using JACKSON and then use StrSubstitutor to replace the placeholders in my application json with proper values from response json(My Application string with placeholders Shown below).
{"order_number":"${orderNumber}","order_date":"${orderDate}","bill_to_name":"${Billing.name}","bill_to_address":"${Billing.Address}","bill_to_city":"${Billing.City}","ship_from_name":"${Shipping.Name}","ship_from_Address":"${Shipping.Address}","ship_from_city":"${Shipping.City}"}
But the issue i faced was that
JSON to MAP didn't work with nested JSONOBJECT as shown in the response above.
Also to substitute Billing.Name/Shipping.Name etc, even if i extract the Shipping/Billing JSONObjects from the response, when i
would convert them to hashmap, they would give me Name, City,
Address1 as keys and not Billing.Name, Billing.City etc.
So as a solution i wrote the below piece of code which takes the response JSONObject(srcObject) and JSONObject of my application(destObject) as inputs, performs processing and fits in the values from the response JSON into my application JSON.
public void mapJsonToJson(final JSONObject srcObject, final JSONObject destObject){
for(String key : destObject.keys()){
String srcKey = destObject.getString(key)
if(srcKey.indexOf(".") != -1){
String[] jsonKeys = srcKey.split("\\.")
if(srcObject.has(jsonKeys[0])){
JSONObject tempJson
for(int i=0;i<jsonKeys.length - 1;i++){
if(i==0) {
tempJson = srcObject.getJSONObject(jsonKeys[i])
} else{
tempJson = tempJson.getJSONObject(jsonKeys[i])
}
}
destObject.put(key, tempJson.getString(jsonKeys[jsonKeys.length - 1]))
}
}else if(srcObject.has(srcKey)){
String value = srcObject.getString(srcKey)
destObject.put(key, value)
}
}
}
The issue with this piece of code is that it takes some time to process. I want to know is there a way i can implement this logic in a better way with less processing time?
You should create POJOs for your two data types, and then use Jackson's mapper to deserialize the REST data in as the first POJO, and then have a copy constructor on your second POJO that accepts the POJO from the REST service, and copies all the data to its fields. Then you can use Jackson's mapper to serialize the data back into JSON.
Only if the above still gives you performance issues would I start looking at faster but more difficult algorithms such as working with JsonParser/JsonGenerator directly to stream data.
I feel the standard approach will be to use XSLT equivalent for JSON. JOLT seems to be one such implementation. Demo page can be found here. Have a look at it.
I want to generate a JSON String in the following structure using Jackson API (JsonFactory,JsonGenerator). How can i do it ?
Expected:
{
"api": {
"Salutaion": "Mr",
"name": "X"
},
"additional": {
"Hello",
"World"
}
}
Actual:
{
"api": "{
\"Salutaion\": \"Mr\",
\"name\": \"X\"
}",
"additional": "{
\"Hello\",
\"World\"
}"
}
The values of the attributes api & additional will be available to me as String. Should i be using writeObjectField (as follows) ?
jGenerator.writeObjectField("api", apiString);
After constructing the jGenerator object, how do i get the final constructed JSON Object's String representation ?
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
JsonGenerator jGenerator = jfactory.createJsonGenerator(outputStream);
jGenerator.writeStartObject();
jGenerator.writeObjectField("api", apiString);
jGenerator.writeObjectField("additional", additionalString);
jGenerator.writeEndObject();
jGenerator.close();
outputStream.close();
outputStream.toString()
The outputStream.toString() gives a json string but the double quotes (") in the apiString are getting prefixed with an escape character \
Is this the right way ?
Assuming apiString and additionalString are references to String objects with JSON content, you'll want to write them raw, ie. their content directly. Otherwise, you're serializing them as JSON strings and Jackson will need to escape any relevant characters.
For example
jGenerator.writeFieldName("api");
jGenerator.writeRawValue(apiString);
for api, and the same for additional.