TRUE or FALSE into boolean using Jackson JSON parsing - java

I am using Jackson annotation for parsing JSON response into POJO object.I was using boolean variable in POJO for mapping values "true" and "false" coming from JSON. But suddenly we are getting value as "TRUE" and "FALSE" into JSON and parsing failing for these values.
Can anyone suggest way to map it to boolean as this variable is used so many places where i don't want to change logic to String to Boolean .

It isn't really an issue, this is basically the way BeanUtils works.
For boolean vars, Jackson removes is from the setter name to derive what it expects the variable name to be when marshalling to JSON and adds set to that same derived name to unmarshal back to a POJO.
So boolean isFooTrue; ends up as fooTrue when marshalled to JSON, and when unmarshalling it would attempt to call setIsFooTrue();, which isn't the correct.
If you're using an IDE and you generated your getter/setters, you'll probably notice that the generated code for boolean isFoo; basically ignores the is as if the var name was just foo:
private boolean isFoo;
public boolean isFoo() {
return isFoo;
}
public void setFoo(boolean isFoo) {
this.isFoo= isFoo;
}
Two options are to remove the is from the var name, or add the is to the setter name.

I am not sure this is what you want.
But it works.
Boolean param = Boolean.parseBoolean((String)yourValue);
The tested code is
public class program10 {
public static void main(String args[]) {
String yourValue = "TRUE"; // This is what you get from json.
Boolean param = Boolean.parseBoolean((String)yourValue);
if(param == true)
System.out.println("Value is true");
else
System.out.println("Value is false");
System.out.println(param);
}
}

I also faced a similiar issue using Jackson Parser 1.8.5.
Java POJO to JSON worked but same JSON back to Java POJO did not.
In Java POJO, if a boolean variable is declared as
private Boolean isMyVar;
then the Jackson produces equivalent JSON as
{..,
"myVar" : false,
..
}
(I know the boolean variable naming is wrong here, but the JAR is third party and say you cannot change it!)
I think this is an issue with the way Jackson parser is designed to handle boolean values.
I changed the JSON from "myVar" : false to "isMyVar" : false and it worked ok to create back the Java POJO from the JSON.
Anybody knows if this is still a bug or has it been resolved?

Related

Jackson infinite recursion when converting to json

When trying to convert a custom object Tag which has the below structure to json, it gives me the following error: java.lang.IllegalArgumentException: Infinite recursion because of getValueArray() function
public class Tag {
private String vr;
#JsonProperty("Value")
private JsonNode Value;
//getters and setters
public org.primefaces.model.TreeNode getValueArray() throws IOException
{
System.out.println("enter check");
TreeNode root = new DefaultTreeNode();
constructTree(Value, 1, root);
return root;
}
}
I have a getter for Value that returns String instead of JsonNode (for specific reason), and I have this getValueArray that causes the problem, Jackson calls this function when converting to json instead of using getValue (I know that as enter check are printed to console), actually when I remove this function it works, for some reason it calls this function and uses the returned TreeNode in it's conversion, I thought the problem might be that it gets confused with Jackson treeNode, so I returned org.primefaces.model.TreeNode to let it recognizes that this is primefaces TreeNode not Jackson TreeNode, I don't even know why it calls this function, and how to fix this.
the error said
java.lang.IllegalArgumentException: Infinite recursion (StackOverflowError) (through reference chain: org.primefaces.model.DefaultTreeNode["parent"]->org.primefaces.model.DefaultTreeNode["children"]->org.primefaces.model.TreeNodeChildren[0]->org.primefaces.model.DefaultTreeNode["parent"]................. and so on
I found a work around that works fine, as the problem is that Jackson uses this function getValueArray() as a getter in the serialization, because of it's name get something, I used
#JsonGetter("valueArray")
public JsonNode serializeValue()
{
return Value;
}
#JsonGetter("valueArray") lets me force Jackson to use the above function as getter for the non exist property valueArray which return the Value, now jackson will no longer uses getValueArray() function as getter.

How can I deserialize a list of enums using Jackson JSON?

I'm working on a configuration system. I'd like to be able to load config values from a JSON file and have them "automagically" convert to the Java type I need. I'm using Jackson for the JSON parsing. For primitive types like floats and strings, it's no big deal, but I'm running into a snag with enums.
Let's say I have the following enum:
public enum SystemMode
{
#JsonProperty("Mode1")
MODE1("Mode1"),
#JsonProperty("Mode2")
MODE2("Mode2"),
#JsonProperty("Mode3")
MODE3("Mode3");
private final String name;
private SystemMode(String name)
{
this.name = name;
}
#Override
#JsonValue
public String toString()
{
return this.name;
}
}
Now, let's say I want to represent a list of values of this enum for a given config variable using the following JSON representation:
{
"Project" : "TEST",
"System" : {
"ValidModes" : ["Mode1", "Mode2"]
}
}
And I'd like to be able to do something like the following:
ArrayList<SystemMode> validModes = (ArrayList<SystemMode>) configurator.getConfigValue("/System/ValidModes");
For reference, my configurator class's getConfigValue method is essentially a thin wrapper over the Jackson JSON parsing:
public Object getConfigValue(String JSON_String)
{
JsonNode node = JsonNodeFactory.instance.objectNode().at(JSON_String);
return objectMapper.convertValue(node, Object.class);
}
(The real method has some exception checking that has been omitted for clarity).
Now, when I call the above, Jackson correctly deduces that I want an ArrayList and fills it. However, instead of getting an ArrayList of SystemMode enums, I get an ArrayList of Strings and immediately throw an exception when I attempt to use the list. I have tried several different ways of representing the data to no avail. It seems no matter what I try, Jackson wants to return a list of strings instead of a list of enums.
So my question is this:
How can I make Jackson (version 2.9.4) JSON properly deserialize a list of enum values in a way that is compatible with my single "Object getConfigValue()" method?
The following will provide the correct binding for your enum.
public List<SystemMode> getConfigValue(String path)
{
JsonNode node = JsonNodeFactory.instance.objectNode().at(path);
return objectMapper.convertValue(node, new TypeReference<List<SystemMode>>(){});
}
The second option is to convert the list of String yourself, for example:
List<SystemMode> result = jsonResult.stream().map(SystemMode::valueOf).collect(Collectors.toList());
Third option:
public <T>List<T> getConfigValue(String path, Class<T> type)
{
JsonNode node = JsonNodeFactory.instance.objectNode().at(path);
CollectionType toType =
objectMapper.getTypeFactory().constructCollectionType(List.class, type);
return objectMapper.convertValue(node, toType);
}

How to identify the fields having default values when deserialized using jackson

I have a class Person and I want to deserialize a POJO from a JSON using jackson. Now,
the definition to Person class is something like :
class Person {
int id;
String name;
boolean isOldAge;
boolean hasSenseOfHumor;
.
.
.
}
Now my json is something like :
{
"id" : 1,
"isOldAge" : false
}
Now when I deserialize this into a POJO the values I will get would be :
[id=1,name="",isOldAge=false,hasSenseOfHumor=false]
i.e, the properties not mentioned in json will be assigned their default values.
So my problem lies here. Is there a way I can distinguish isOldAge from hasSenseOfHumor with respect to whether it is mentioned or provided for by the user or not.
Try to change the primitive boolean to the boxing Boolean type. The fields should be initialised with null values then.
If you cannot change field types of the class, then can read your JSON as map in advance as follows mapper.readValue(JSON, Map.class), and then reason about the presence of the boolean fields in the resulting map instance.

Gson serialization depending on field value

I have a POJO that is similar to:
public class MyGsonPojo {
#Expose
#SerializedName("value1")
private String valueOne;
#Expose
#SerializedName("value2")
private boolean valueTwo;
#Expose
#SerializedName("value3")
private int valueThree;
// Getters and other stuff here
}
The issue is that this object has to be serialized into a json body for a call
to the server. Some fields are optional for the request and if I even send it with default and null values, the API responds differently (Unfortunately changing the api is not an option).
So basically I need to exclude fields from serialization if any of them is set to a default value. For example if the field valueOne is null the resulting json should be:
{
"value2" : true,
"value3" : 2
}
Any idea how to make this a painless effort? I wouldn't want to build the json body manually.
Any help would be great. Thank you in advice.
Steps to follow:
Convert the JSON String into Map<String,Object> using Gson#fromJson()
Iterate the map and remove the entry from the map which are null
Form the JSON String back from the final map using Gson#toJson().
I have already posted the sample code in the same context here:
Remove empty collections from a JSON with Gson
Option 1) Use a TypeAdapter, see accepted answer here:
Option 2) If using Jackson instead of gson is a possibility, you can annotate/serialize on getters instead of on fields, and put your logic for returning
whatever you need for "default values" in your getters.
//won't get serialized because it's private
private String valueOne;
...
#JsonSerialize
String getValueOne(){
if (valueOne == null) return "true"
else...
}
You could also use a single #JsonInclude(Include.NON_NULL) or #JsonInclude(Include.NON_EMPTY) annotation at the top of your class to prevent any null or empty fields from being serialized.

Getter (accessor) based serialization (json or xml)

I need to serialize a couple of objects in my Android app and send them to web service.
The model classes for objects have various int fields which need to be converted into meaningful string representations from various arrays before sending to web service.
So, I am assuming that easiest way will be to use gson or xstream (JSON or XML - anything is fine) but with following method:
- I'll mark all existing int fields as transient and exclude them from serialization
- I'll create new get method per field. The get method will read value of corresponding integer and return its string representation.
But in either of 2 libraries - gson or xstream, I am unable to find way to serialize based on getters instead of fields. Please suggest.
And yes, I DO NOT need to deserialize the data back.
I think you need a wrapper class.
Consider this:
public class Blammy
{
private int gender;
... imagine the rest of the class.
}
public class BlammyWrapper
{
private String gender;
public BlammyWrapper(final Blammy blammy)
{
if (blammy.gender == 1)
{
gender = "Its a Boy";
}
else if (blammy.gender == 2)
{
gender = "girl";
}
else // always check your boundary conditions.
{
throw new InvalidArgumentException("Naughty blammy; unrecognized gender value");
}
public String gender()
{
return gender;
}
}
Ok, finally, I followed this approach:
1. Removed all resource arrays from my app code
2. Added enums with toString for each current array
3. Changed all int properties to be of corresponding enum type
4. Used XStream
5. Added a custom convertor for XStream for generic enum types where if it finds any property of type enum, then it will marshal it using toString method.
Thanks for all support btw. All your answers and comments atleast made me clear that my current code architecture needed drastic improvement.

Categories