java objectmapper readvalue reading wrong string - java

I need to convert a certain JSON string to a Java object. I am using Jackson ObjectMapper for reading the JSON. The JSON String is something like this:-
"{"emailId":"gmail#rajnikant.com","accessToken":"accTok"}4".
When I am using objectMapper.readValue() for reading the JSON string to a specific destination class, it should throw an exception because of the JSON string being appended by 4. What should I do so that only valid JSON can be read and in other cases it will throw an exception?

To Jackson, GSON and others, a JSON string with some characters appended after the last } is valid JSON as long as what is contained between the {} is valid JSON.
As stated by a member of FasterXML (Jackson) team:
Yes. This is by design. If you want to catch such problems, you need to construct JsonParser, advance it manually. Existence of multiple root-level values is not considered a validity problem.
Reference: https://github.com/FasterXML/jackson-databind/issues/726
So if you need to enforce "clean" JSON you'll have to extend the default parser with your own functionality. However, IMO if it's OK to the default parser it should be OK to you too (unless we're dealing with some inter-language incompatibility scenario here).

Related

Can JSON field not be a string?

As far as I know, all JSON field names are string values. However, I encountered a code snippet that does a string check on the "keys" of JSON to see if it's a string, and if not, it throws an exception. It goes something like:
if (!(key instanceof String)){
throw new exception();}
Is this check necessary?
EDIT:
For example,
while (jp.nextToken() == JsonToken.FIELD_NAME){
String key = jp.getCurrentName();
}
This code snippet will only progress to JSON tokens that are strings, so I was wondering if a JSON could contain fieldnames that are not strings so that Jackson parser will simply skip those fieldnames.
From the JSON official website (and by proxy, the JSON Data Interchange Standard):
When creating an object, the key must be a String.
EDIT: As #SotiriosDelimanolis pointed out in the comments, this only applies to the format of the JSON file, not necessarily once parsed through a Java library.
Jackson, for example, can deserialize keys into custom types - #SotiriosDelimanolis

Parse json array with quotes around it

I'm calling 3rd party API and receiving as a response next string:
"[{\"name\":\"name\",\"id\":1}]"
As I see it's not valid json because it has quotes around it. Is it possible somehow to map it to java object with jackson, gson libraries?
Or anyway I should write my custom converter/deserializer?
You don't need a custom converter or deserializer. You could write one of course, but I wouldn't encourage you to do so. Be explicit about what is happening here, especially when you are working in a team. It's the other side that is at fault here, they are not outputting valid JSON.
With Jackson, deserialize their output this way:
ObjectMapper mapper = new ObjectMapper();
String json = theirOutput.substring(1, theirOutput.length - 1);
Object myObject = mapper.readValue(json, MyObject.clas);
Put some documentation above why you do it this way so everybody understands what's happening here. In my opinion this is a much cleaner solution than writing a custom converter or deserializer.

Best Way To Test For Correct JSON Serialization

I use the Jackson library with Java to serialize POJOs to JSON and vice versa. Let's say that I am running some tests where I am serializing an object and I know that the expected JSON string is {"firstName":"John", "lastName":"Doe"}. What is the best way to validate that my object serialized to the above string? Or better yet, what is the best way to validate that each of the fields is what I expect?
I have tried simply hard coding that string in and doing a comparison, but I have had cases where I serialize to JSON -> deserialize to POJO -> then serialize the deserialized POJO back to JSON again, and the fields are out of order. Then the string comparison fails even though all of the fields are correct.
Is there are better/different way to verify that my JSON string has the expected fields in it when testing?
I ran into the exact same situation as you and found JSONassert to be very helpful.
In your JUnit test you would have to add something like this:
String actual = getSerializedContent();
String expected = "{firstName:\"John\", lastName:\"Doe\"}";
JSONAssert.assertEquals(expected, actual, false);

Object to Json including only fields not null

I have an object named Item with plenty of fields. I'm using a Java JSON (json-io) library to serialize its state in a File:
String json = JsonWriter.objectToJson(item);
// Write String to File
I'd like to make the json String less verbose so that it does not include null values (if possible also boolean which are false). Is it possible to do it somehow ?
Thanks
I can recommend using jackson mapper if possible.
Check out these two questions:
Jackson serialization: ignore empty values (or null)
How to tell Jackson to ignore a field during serialization if its value is null?

How can I log discarded fields when deserializing with GSON?

I am using JSON as a save format.
If I change the field names of my object GSON will silently discard the original fields upon loading the older version, because they no longer match the new names.
I would like to be able to get some notification if I do this accidentally through refactoring, i.e. "Warning: variableName not found in ObjectType during deserialization."
There is a #Version annotation but it isn't exactly what I'm looking for.
Has anyone written a custom deserializer or custom type converter that will throw an error when a field in the JSON does not exist in the type? Is there another serialization library that does this?
Edit: I would still be interested in a GSON deserializer that does this as well, if anyone has one.
Jackson can be used to fail on unexpected JSON elements. Jackson can also be configured to gather (and log) all unbound JSON elements, as described at http://www.cowtowncoder.com/blog/archives/2010/09/entry_414.html (search for "any setter").
If you're already familiar with Gson, I documented how to use Jackson to do the same things covered in the Gson User Guide at http://programmerbruce.blogspot.com/2011/07/gson-v-jackson-part-6.html.

Categories

Resources