In my project I'm using GSON to serialize and deserialize objects. Often I get a list of objects as JSON from a server but I'm only interested in the first element of the list. Is it possible with #SerializedName to only fetch the first element of the list?
I think about something like this: #SerializedName("List[0]")
Or what would you recommend to only parse the first element and not the whole list?
You should use a custom JsonDeserializer:
private class MyCustomDeserializer implements JsonDeserializer<MyModel> {
#Override
public MyCustomDeserializer deserialize(JsonElement json, Type type,
JsonDeserializationContext context) throws JsonParseException {
// initialize an instance of your model
MyModel myModel = new MyModel();
JsonArray jArray = (JsonArray) json; // get json array
JsonObject jsonObject = (JsonObject) jArray.get(0); // get first object
// do what you want with the first object
myModel.setParameter(jsonObject.get("parameter").getAsInt());
// ignore next json objects
return myModel;
}
}
Then, initialize your Gson instance like this:
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(MyModel.class, new MyCustomDeserializer());
Gson gson = gsonBuilder.create();
MyModel model = gson.fromJson(jsonString, MyModel.class);
If you want to exclude some fields from Serialization you need to declare them in your model as transient:
private transient String name; // will be ignored from Gson
Related
I need to deserialize a Json file that has an array. I know how to deserialize it so that I get a List object, but in the framework I am using a custom list object that does not implement the Java List interface. My question is, how do I write a deserializer for my custom list object?
EDIT: I want the deserializer to be universal, meaning that I want it ot work for every kind of list, like CustomList<Integer>, CustomList<String>, CustomList<CustomModel> not just a specific kind of list since it would be annoying to make deserializer for every kind I use.
This is what I came up with:
class CustomListConverter implements JsonDeserializer<CustomList<?>> {
public CustomList deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext ctx) {
Type valueType = ((ParameterizedType) typeOfT).getActualTypeArguments()[0];
CustomList<Object> list = new CustomList<Object>();
for (JsonElement item : json.getAsJsonArray()) {
list.add(ctx.deserialize(item, valueType));
}
return list;
}
}
Register it like this:
Gson gson = new GsonBuilder()
.registerTypeAdapter(CustomList.class, new CustomListConverter())
.create();
I need to convert a java object (called org) to json format.
The object (DTO ) is a bit complex, because it contains a list of objects of the same class and which in turn can also contain more objects of the same class ( built recursively). When I passing the object to gson.toJsonTree method it seems to fail (there isnt any error), but it seems that the method does not like complex objects). If I set to null the list of objects of the first object everything works fine. I can not modify the class, only the method that makes json.
JsonElement jsonUO = null;
jsonUO = gson.toJsonTree(org,OrgDTO.class);
jsonObject.add("ORG", jsonUO)
public class OrgDTO implements Serializable{
private String id;
......
private List sucesores;
public OrgDTO(){
this.sucesores = new ArrayList();
}
.....
}
It might be a little bit late for the questioner, however I share my answer in case someone else face similar issue:
You'll need to create a helper class that does the json serialization. It should implement the JsonDeserializer:
public class OrgDTOJsonSerializer implements JsonDeserializer<OrgDTO> {
#Override
public JsonElement serialize(OrgDTO src, Type type, JsonSerializationContext jsc) {
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("id", src.getId());
/// Build the array of sucesores (whatever it means!)
JsonArray sucesoresArray = new JsonArray();
for (final OrgDTO obj: src.getSucesores()) {
JsonObject succJsonObj = serialize(obj, type, jsc);
sucesoresArray.add(succJsonObj);
}
jsonObject.add("sucesores", sucesoresArray);
return jsonObject;
}
}
Then you'll need to register it in gson before attempting to serialize any object of that type:
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(OrgDTO.class, new OrgDTOJsonSerializer());
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)
when deserializing a json into a class Foo{int id; List<String> items; List<Long> dates;} How could I auto initialize fields that are null after deserialization. Is there such a possiblity with Gson lib?
ex:
Foo foo = new Gson().fromJson("{\"id\":\"test\", \"items\":[1234, 1235, 1336]}", Foo.class)
foo.dates.size(); -> 0 and not null pointerException
I know I could do if (foo.attr == null) foo.attr = ...
but I'm looking for more generic code, without knowledge of Foo class
thx
edit: sorry just putting Getters in Foo is enough
closed
You need to create your custom deserializer.
Assuming your class is called MyAwesomeClass, you implement something like
MyAwesomeClassDeserializer implements JsonDeserializer<MyAwesomeClass> {
#Override
public MyAwesomeClass deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext ctx) throws JsonParseException
{
// TODO: Do your null-magic here
}
and register it with GSON, like this:
Gson gson = new GsonBuilder()
.registerTypeAdapter(MyAwesomeClass.class, new MyAwesomeClassDeserializer())
.create();
Now, you just call a fromJson(String, TypeToken) method, to get your deserialized object.
MyAweSomeClass instance = gson.fromJson(json, new TypeToken<MyAwesomeClass>(){}.getType());
Let's imagine I have a Java class of the type:
public class MyClass
{
public String par1;
public Object par2;
}
Then I have this:
String json = "{"par1":"val1","par2":{"subpar1":"subval1"}}";
Gson gson = new GsonBuilder.create();
MyClass mClass = gson.fromJson(json, MyClass.class);
The par2 JSON is given to me from some other application and I don't ever know what are it's parameter names, since they are dynamic.
My question is, what Class type should par2 variable on MyClass be set to, so that the JSON String variable is correctly deserialized to my class object?
Thanks
Check out Serializing and Deserializing Generic Types from GSON User Guide:
public class MyClass<T>
{
public String par1;
public T par2;
}
To deserialize it:
Type fooType = new TypeToken<Myclass<Foo>>() {}.getType();
gson.fromJson(json, fooType);
Hope this help.
See the answer from Kevin Dolan on this SO question: How can I convert JSON to a HashMap using Gson?
Note, it isn't the accepted answer and you'll probably have to modify it a bit. But it's pretty awesome.
Alternatively, ditch the type safety of your top-level object and just use hashmaps and arrays all the way down. Less modification to Dolan's code that way.
if you object has dynamic name inside lets say this one:
{
"Includes": {
"Products": {
"blablabla": {
"CategoryId": "this is category id",
"Description": "this is description",
...
}
you can serialize it with:
MyFunnyObject data = new Gson().fromJson(jsonString, MyFunnyObject.class);
#Getter
#Setter
class MyFunnyObject {
Includes Includes;
class Includes {
Map<String, Products> Products;
class Products {
String CategoryId;
String Description;
}
}
}
later you can access it:
data.getIncludes().get("blablabla").getCategoryId()
this code:
Gson gson = new GsonBuilder.create();
should be:
Gson gson=new Gson()
i think(if you are parsing a json doc).