Not all fields serialized by toJson() - java

I'm using Gson 2.2's toJson() method to serialize a java object into a json string. The java object is of type:
public class LOB implements Serializable{
private int id;
private LOBType type;
private TypeSpecificData data;
public class TypeSpecificData {
private String a;
private int b;
}
}
All fields of the object are serialized except for data field of type TypeSpecificData.
How do I include this field as well in the json string ?
Currently I'm serializing like shown below:
String jsonString = new Gson().toJson(lob_instance);

By default Gson will not serialize null objects refereces. Please check it.
Link to GSON documentation

Related

Gson why does my deserialization not work?

I am trying to make a java program that will need to work with json, I have choose gson as my library to handle managing JSON
But when I try to deserialize my json the messagereturn.text value and the messagereturn.extra.text value both get set as null, I have tried to fix this but I am unable to.
An example of the json that i am trying to deserialize is
{
"text":"",
"extra":[{
"text":"eee joined the game",
"color":"yellow"
}]
}
And this is how I am calling gson
Message messagepacket = event.<ServerChatPacket>getPacket().getMessage();
//this gets the json data
messagereturn messagereturn = gson.fromJson(String.valueOf(messagepacket), messagereturn.class);
System.out.println(messagereturn.returnmethod());
Here is the class I am trying to deserialize too
public class messagereturn {
String text;
public class extra{
String text;
}
public String returnmethod() {
extra extra = new extra();
return text + extra.text;
}
}
Thank you, if there is any more informaton needed let me know, thanks
There is a problem understanding your JSON (and creating the Java classes by the way). These marks [] means that is a list.
So you have an object with atributes text, type String and extra, type List<Object>.
This list contains another object (note that the object is defined by {} and list by []).
The object into the list has another two attributes: text and color both with primitive types; String.
So your java class should be like this:
public class Messagereturn {
private String text;
private List<Extra> extra;
//getters and setters and other methods
}
And the class Extra:
public class Extra {
private String text;
private String color;
//getters and setters
}
With this data model you can call your Gson with these structure.
Also, you don't need to call returnMethod to create Extra object, it is created by Gson.
Using this line of code:
Messagereturn mr = new Gson().fromJson(txt, Messagereturn.class);
And your JSON example, this is the value stored when run in debug mode:
As you can see, tha values from JSON has been created and loaded into memory.

Gson - deserialize unknown classes

Lets say I have a group of classes A,B,C:
public class A:
int number;
public class B:
int number;
String address;
public class C:
int orderNumber;
How can i deserialize a Json string which contains only these classes, but in an unknown order (using Gson, in Java)? For example:
{//A
"number" : 3
}
//C
{
"orderNumber": 10
}
//B
{
"number" : 5
"address" : "New York"
}
//C
{
"orderNumber": 1
}
Thank you very much!
Answer by pirho is clean and easy if, like he said, your classes are simple as you've provided. But if that isn't the case, you can write your own deserializer.
public class PayloadJsonDeserializer implements JsonDeserializer {
#Override
public Object deserialize(JsonElement elm, Type type, JsonDeserializationContext context) throws JsonParseException {
// create java objects based on the properties in the json object
JsonPrimitive orderNumber = elm.getAsJsonObject().getAsJsonPrimitive("orderNumber");
if(!orderNumber.isJsonNull()) {
return new C(orderNumber.getAsInt());
}
return null;
}
}
Register your custom deserializer with Gson.
GsonBuilder gsonBuilder = new GsonBuilder()
.registerTypeAdapter(PayloadJson.class, new PayloadJsonDeserializer());
Gson gson = gsonBuilder.create();
Use it to deserialize your json.
gson.fromJson(jsonString, PayloadJson[].class);
This is not a generic or anyway a great strategy to do this in general if you have more complex classes with more fields.
But if the classes you want to deserialize are as simple as you provide as an example then create a class having all these fields
#Getter
public class Z {
private Integer orderNumber;
private Integer number;
private String address;
}
You will get a list of Zs and depending on which of the field are null or not null you can -if needed - later construct A, B or C from Z.
If classes to deserialize are more complex you anyway need to create some kind of a mechanism that determines what is the class to parse and to return. It could be like user1516873 suggested in the comment
Collection<Map<String,String>>
so for each item you would need to determine by what fields are present in that map to what class - A,B or C - item would be constructed.

Keep object as string in json deserialization

I have a class with some fields and extra data of type string that will store a json object. I want it to not be deserialized, but after looking for more than an hour, the only thing I found was:
#Expose(deserialize=false)
But It doesn't work.
The following is an example:
public class Employee implements Serializable
{
private static final long serialVersionUID = 1L;
#Expose
public Long id;
#Expose
public String name;
... some more fields
#SerializedName("extraData")
#Expose(deserialize = false)
public String extraData;
}
Then on my service I do the following:
final GsonBuilder builder = new GsonBuilder();
final Gson gson = builder.create();
Employee emp = gson.fromJson(json, Employee.class);
The object I am receiving from the frontend is:
{
"id":1,
"name": "John Doe",
"extraData": {"someField1":"someValue1","someField2":"someValue2"}
}
And I get this error:
java.lang.IllegalStateException: Expected a string but was BEGIN_OBJECT at line 1 column 48 path $.extraData
When I just want to get "extraData" as an string with the value
{"someField1":"someValue1","someField2":"someValue2"}
Other solutions are not accepted because it is the spec i was given.
It does not harm if you change the type of extraData like (assuming it is possible and the extra data follows the pattern you described)
public Map<String, String> extraData;
and compose a String of it.
Still what Jaron F suggested might be better in whole. For using type adapter see this answer
You should use TypeAdapters for this and then add the TypeAdapter into your gson builder during the object creation.
https://google.github.io/gson/apidocs/com/google/gson/TypeAdapter.html

Converting nested JSON to Java Object(An Interface having impl)

I am in need to convert nested JSON to Java Object which is an Interface.
Kindly refer the below example,that JSON string needs to convert into Java Object of type Root.
JSON: {"ROOT":{"NAME":"EVEN"}}
Java:
Interface Root {
String getName();
}
class RootImpl implements Root{
private String name;
public String getName() {
return name;
}
}
Like the below usecase i need to convert nested json of large depth to Java Object.
you can do it with:-
JSONSerializer.toJava(jsonString);
You can use the org.json. Java parser.
public class RootImpl implements Root{
private JSONObject root;
public RootImpl(String json) {
this.root = new JSONObject(json).getJSONObject("ROOT");
}
public String getName(){
return root.getString("NAME");
}
}
Root root = new RootImpl("{\"ROOT\":{\"NAME\":\"EVEN\"}}");
System.out.println(root.getName()); // prints: EVEN
References:
JSON Java API docs
The Google GSON can help you !
"Gson is a Java library that can be used to convert a Java object into its
JSON representation. It can also be used to convert a JSON string into an
equivalent Java object. Gson can work with arbitrary Java objects including
pre-existing objects that you do not have source-code of." --Google-Gson 'README'
Download url:
https://code.google.com/p/google-gson/downloads/list
code example:
//UserInfo object to json string
public String toJson(UserInfo userInfo){
//com.google.gson.Gson
return new Gson().toJson(userInfo);
}
//json string to UserInfo object
public UserInfo fromJson(String jsonStr){
return new Gson().fromJson(jsonStr, UserInfo.class);
}

Is it possible to deserialize JSON property names with periods as a nested object using GSON?

This is an example of the kind JSON I'm trying to consume using GSON:
{
"person": {
"name": "Philip"
"father.name": "Yancy"
}
}
I was wondering if it were possible to deserialize this JSON into the following structure:
public class Person
{
private String name;
private Father father;
}
public class Father
{
private String name;
}
So that:
p.name == "Philip"
p.father.name == "Yancy"
Currently I am using #SerializedName to obtain property names containing a period, e.g.:
public class Person
{
private String name;
#SerializedName("father.name")
private String fathersName;
}
However, that's not ideal.
From looking at the documentation it doesn't appear to be immediately possible but there may be something I have missed - I'm new to using GSON.
Unfortunately I cannot change the JSON I'm consuming and I'm reluctant to switch to another JSON parsing library.
As far as I understand you can't do it in a direct way, because Gson will understand father.name as a single field.
You need to write your own Custom Deserializer. See Gson user's guide instructions here.
I've never tried it, but it doesn't seem to be too difficult. This post could be also helpful.
Taking a look at Gson's user guide and the code in that post, you'll need something like this:
private class PersonDeserializer implements JsonDeserializer<Person> {
#Override
public Person deserialize(JsonElement json, Type type,
JsonDeserializationContext context) throws JsonParseException {
JsonObject jobject = (JsonObject) json;
Father father = new Father(jobject.get("father.name").getAsString());
return new Person(jobject.get("name").getAsString(), father);
}
}
Assuming that you have suitable constructors...
And then:
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Person.class, new PersonDeserializer());
Gson gson = gsonBuilder.create();
Person person = gson.fromJson(jsonString, Person.class);
And Gson will call your deserializer in order to deserialize the JSON into a Person object.
Note: I didn't try this code, but it should be like this or something very similar.
I couldn't do this with just Gson. I need a new library 'JsonPath'. I used Jackson's ObjectMapper to convert the object to string but you can easily use Gson for this.
public static String getProperty(Object obj, String prop) {
try {
return JsonPath.read(new ObjectMapper().writeValueAsString(obj), prop).toString();
} catch (JsonProcessingException|PathNotFoundException ex) {
return "";
}
}
// 2 dependencies needed:
// https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core
// https://mvnrepository.com/artifact/com.jayway.jsonpath/json-path
// usage:
String motherName = getProperty(new Person(), "family.mother.name");
// The Jackson can be easily replaced with Gson:
new Gson().toJson(obj)

Categories

Resources