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

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.

Related

Find a comparable value inside an array property within an Entity

How do you find if a property that is an array contains a value, what is available by default to Xodus is txn.find(entityType, propertyName, comparableValue) to find a value, however, what is the best way to find if an array property contains a value. Suppose I have this:
public class EmbeddedArrayIterable implements Serializable, ByteIterable {
}
In which I need to compare if a given value, example "cat", is inside the array. What should be the implementation of EmbeddedArrayIterable as such it will be able to return the Entity to which this "cat" string is in the array of the entity.
As such we can do:
// This property is a `EmbeddedArrayIterable`
// which is a serialized JSON like `["cat","tiger","lion"]`
String propertyName = "keywords";
String comparableValue = "cat";
EntityIterable cats = txn.find(entityType, propertyName, comparableValue);
If you define a custom property type, then you cannot find an entity by only a part of its value. In your case, it makes sense to use ComparableSet value type provided out-of-the-box. Set the property value as a set of items:
final ComparableSet<String> propValue = new ComparableSet<>();
propValue.addItem("cat");
propValue.addItem("tiger");
propValue.addItem("lion");
entity.setProperty("keywords", propValue);
You can then get the value using Entity#getProperty(..), cast to ComparableSet<String> and modify the set if necessary. You can also find the entity by only a single item of the set:
EntityIterable cats = txn.find(entityType, "keywords", "cat");

Get value from object by key in java

I am getting object in the response of entityManager.find method.
and i want to get values from that object by passing key. but i din't get any success.
For example :-
my entity :-
#entity
class Test (){
public Long id;
public String name ;
public String descr;
}
and i am getting object in the response of below code.
`Object obj=`entitymanager.find(classname,id);
Note :- Instead of object i can't use entity's object directly because input class name can be dynamically pass that's why i am taking response in Object.
Now i want to get value from object by passing key
something like that obj.getvalue("id");
I tried below things to make it done :-
Map<String, Object> user = (Map<String, Object>)obj;
Used json simple parser to parse it.
JSONParser parser = new JSONParser();
JSONObject jsonObject =parser.parse(obj.toString());
But din't get any success.
Please help me out.
I'm a little unsure of what you're asking... but as long as "name" is a primary key you can call
Test obj = entitymanager.find(Test.class, name);
Object obj=entitymanager.find(classname,id);
In the above line what is the type of "classname".
Since your question does not mention the type. I assume its of type Object.
You should do something like
Object obj=entitymanager.find(classname.getClass(),id);

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);
}

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.

TRUE or FALSE into boolean using Jackson JSON parsing

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?

Categories