https://stackoverflow.com/questions/39114293/why-jsonnull-in-gson
https://howtodoinjava.com/gson/serialize-null-values/
https://www.mkyong.com/java/how-do-convert-java-object-to-from-json-format-gson-api/
https://github.com/google/gson/issues/1104
This leads to either including the source code, or relying on 3rd party artifacts (outdated)
That is by design. We have no intention of maintaining backward compatibility on extras. You should include source-code
https://github.com/google/gson/blob/master/extras/src/main/java/com/google/gson/typeadapters/RuntimeTypeAdapterFactory.java
https://futurestud.io/tutorials/how-to-deserialize-a-list-of-polymorphic-objects-with-gson
PostConstructAdapterFactory
https://g2.gitblit.com/google/gson/commit/4512f31c698d41cdd97144187fb3ed3b94102768
https://futurestud.io/tutorials/gson-getting-started-with-java-json-serialization-deserialization
Adapter
https://www.tutorialspoint.com/gson/gson_custom_adapters.htm
https://github.com/google/gson/blob/master/UserGuide.md
http://www.vogella.com/tutorials/JavaLibrary-Gson/article.html
JsonElement
JsonPrimitive
JsonObject
JsonArray
JsonNull
Gson gson = new GsonBuilder().setPrettyPrinting().create();
GSON can serialize/deserialize a static nested class implicitly. No additional configuration is required.
Versioning support
@Since(1.0)
class Student {
@Since(1.1) private String gender;
}
gson = new GsonBuilder().setVersion(1.1).setPrettyPrinting().create();
While serializing/deserializing a Java object to and from JSONstring, GSON creates a default instance of that class using its default constructor. It is good to have a default no argument constructor of the Java class. If a class does not have a default constructor, GSON provides a class.google.gson.InstanceCreator interface implementation to deal with it.
class SalaryInstanceCreator implements InstanceCreator<Salary> {
@Override
public Salary createInstance(Type type) {
return new Salary(25000);
}
}
Gson gson = new GsonBuilder().serializeNulls()
.registerTypeAdapter(Salary.class, new SalaryInstanceCreator())
.setPrettyPrinting().create();
@SerializedName("instituteName")
private String name;
class CustomFieldStrategy implements FieldNamingStrategy {
@Override
public String translateName(Field aField) {
String nameOfField = aField.getName();
return nameOfField.toUpperCase();
}
}
.setFieldNamingStrategy(new CustomFieldStrategy())
Gson gson2 = new GsonBuilder().excludeFieldsWithModifiers().create();
Gson, presumably, wanted to model the difference between the absence of a value and the presence of the JSON value
null
in the JSON. For example, there's a difference between these two JSON snippets{}
{"key":null}
your application might consider them the same, but the JSON format doesn't.
Calling
JsonObject jsonObject = new JsonObject(); // {}
jsonObject.get("key");
returns the Java value
null
because no member exists with that name.
Calling
JsonObject jsonObject = new JsonObject();
jsonObject.add("key", JsonNull.INSTANCE /* or even null */); // {"key":null}
jsonObject.get("key");
returns an instance of type
JsonNull
(the singleton referenced by JsonNull.INSTANCE
) because a member does exist with that name and its value is JSON null, represented by the JsonNull
value.Gson gson = new GsonBuilder() .serializeNulls() .create();
|
https://www.mkyong.com/java/how-do-convert-java-object-to-from-json-format-gson-api/
6.1 Convert a JSON Array to a
List
, using TypeToken
String json = "[{\"name\":\"mkyong\"}, {\"name\":\"laplap\"}]";
List<Staff> list = gson.fromJson(json, new TypeToken<List<Staff>>(){}.getType());
list.forEach(x -> System.out.println(x));
6.2 Convert a JSON to a
Map
String json = "{\"name\":\"mkyong\", \"age\":33}";
Map<String, Object> map = gson.fromJson(json, new TypeToken<Map<String, Object>>(){}.getType());
map.forEach((x,y)-> System.out.println("key : " + x + " , value : " + y));
https://github.com/google/gson/issues/1104
gson-extras
is not distributed as part of the main artifact, and there is no independent artifact for it.This leads to either including the source code, or relying on 3rd party artifacts (outdated)
That is by design. We have no intention of maintaining backward compatibility on extras. You should include source-code
String json = gson.toJson(collection); System.out.println("Using Gson.toJson() on a raw collection: " + json); | |
JsonParser parser = new JsonParser(); | |
JsonArray array = parser.parse(json).getAsJsonArray(); | |
String message = gson.fromJson(array.get(0), String.class); | |
https://futurestud.io/tutorials/how-to-deserialize-a-list-of-polymorphic-objects-with-gson
public class Animal {
private String name;
private String type; // this specifies which animal it is
}
public class Dog extends Animal {
private boolean playsCatch;
}
public class Cat extends Animal {
private boolean chasesRedLaserDot;
}
}
String responseJson = new String(responseBody); // from the service endpoint
// which format has the response of the server
final TypeToken<ServiceResponse> requestListTypeToken = new TypeToken<ServiceResponse>() {};
// adding all different container classes with their flag
final RuntimeTypeAdapterFactory<AbstractContainer> typeFactory = RuntimeTypeAdapterFactory
.of(Animal.class, "type") // Here you specify which is the parent class and what field particularizes the child class.
.registerSubtype(Dog.class, "dog") // if the flag equals the class name, you can skip the second parameter. This is only necessary, when the "type" field does not equal the class name.
.registerSubtype(Cat.class, "cat");
// add the polymorphic specialization
final Gson gson = new GsonBuilder().registerTypeAdapterFactory(typeFactory).create();
// do the mapping
final ServiceResponse deserializedRequestList = gson.fromJson(responseJson, requestListTypeToken.getType() );
https://g2.gitblit.com/google/gson/commit/4512f31c698d41cdd97144187fb3ed3b94102768
https://futurestud.io/tutorials/gson-getting-started-with-java-json-serialization-deserialization
An alternative to using
@Expose
is to declare a field as transient
. A transient field will not be (de)serialized either. However, you don't have full control like you do with @Expose
. You cannot deactivate one direction, transient
will always completely turn off the conversion for that property. @Expose(serialize = false, deserialize = false)
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setLenient();
Gson gson = gsonBuilder.create();
By default, Gson will always create an empty instance of the Java model and then set the properties via reflection. Strictly speaking, the constructors you create in your model are not used at all (by Gson). If your Java models act as simple data holders and provide no further logic or functionality, this behavior has no downsides.
However, if your data model does have additional properties that are set by default or dynamically, you'd have to do some hacking to get around Gson's use of reflection. Luckily, Gson covers that use case as well and lets you implement a clean solution with
InstanceCreator
s.GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(
UserContext.class,
new UserContextInstanceCreator(getApplicationContext())
Adapter
https://www.tutorialspoint.com/gson/gson_custom_adapters.htm
GsonBuilder builder = new GsonBuilder(); builder.registerTypeAdapter(Student.class, new StudentAdapter()); Gson gson = builder.create();
class StudentAdapter extends TypeAdapter<Student> { @Override public Student read(JsonReader reader) throws IOException { Student student = new Student(); reader.beginObject(); String fieldname = null; while (reader.hasNext()) { JsonToken token = reader.peek(); if (token.equals(JsonToken.NAME)) { //get the current token fieldname = reader.nextName(); } if ("name".equals(fieldname)) { //move to next token token = reader.peek(); student.setName(reader.nextString()); } if("rollNo".equals(fieldname)) { //move to next token token = reader.peek(); student.setRollNo(reader.nextInt()); } } reader.endObject(); return student; } @Override public void write(JsonWriter writer, Student student) throws IOException { writer.beginObject(); writer.name("name"); writer.value(student.getName()); writer.name("rollNo"); writer.value(student.getRollNo()); writer.endObject(); } }
https://github.com/google/gson/blob/master/UserGuide.md
The Gson instance does not maintain any state while invoking Json operations. So, you are free to reuse the same object for multiple Json serialization and deserialization operations.
To exclude fields you have four options:
- Use the
transient
keyword on your field to indicate that this field not not be serialized. - Gson provides an the
@Expose
from thecom.google.gson.annotations
package which allows to define which fields should be deserialized. You can configure Gson to consider this annotation. - You can register a custom exclusion strategy with the
GsonBuilder
and itssetExclusionStrategies
method. For this you would implement theExclusionStrategy
and itshouldSkipField(FieldAttributes f)
andshouldSkipClass(Class clazz)
methods.
Gson gson = new Gson();
Type type = new TypeToken<List<Task>>() {}.getType();
String json = gson.toJson(list, type);
Gson gson = new Gson();
Staff obj = new Staff();
// 1. Java object to JSON, and save into a file
gson.toJson(obj, new FileWriter("D:\\file.json"));
// 2. Java object to JSON, and assign to a String
String jsonInString = gson.toJson(obj);
1.2
fromJson()
– Convert JSON to Java object
6.1 Convert a JSON Array to a
List
, using TypeToken
String json = "[{\"name\":\"mkyong\"}, {\"name\":\"laplap\"}]";
List<Staff> list = gson.fromJson(json, new TypeToken<List<Staff>>(){}.getType());
list.forEach(x -> System.out.println(x));
6.2 Convert a JSON to a
Map
String json = "{\"name\":\"mkyong\", \"age\":33}";
Map<String, Object> map = gson.fromJson(json, new TypeToken<Map<String, Object>>(){}.getType());
map.forEach((x,y)-> System.out.println("key : " + x + " , value : " + y));
2. To enable the pretty-print, create the Gson
object with GsonBuilder
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String json = gson.toJson(obj);
System.out.println(json);
JsonElement
JsonPrimitive
JsonObject
JsonArray
JsonNull
Gson gson = new GsonBuilder().setPrettyPrinting().create();
GSON can serialize/deserialize a static nested class implicitly. No additional configuration is required.
Versioning support
@Since(1.0)
class Student {
@Since(1.1) private String gender;
}
gson = new GsonBuilder().setVersion(1.1).setPrettyPrinting().create();
While serializing/deserializing a Java object to and from JSONstring, GSON creates a default instance of that class using its default constructor. It is good to have a default no argument constructor of the Java class. If a class does not have a default constructor, GSON provides a class.google.gson.InstanceCreator interface implementation to deal with it.
class SalaryInstanceCreator implements InstanceCreator<Salary> {
@Override
public Salary createInstance(Type type) {
return new Salary(25000);
}
}
Gson gson = new GsonBuilder().serializeNulls()
.registerTypeAdapter(Salary.class, new SalaryInstanceCreator())
.setPrettyPrinting().create();
@SerializedName("instituteName")
private String name;
class CustomFieldStrategy implements FieldNamingStrategy {
@Override
public String translateName(Field aField) {
String nameOfField = aField.getName();
return nameOfField.toUpperCase();
}
}
.setFieldNamingStrategy(new CustomFieldStrategy())
Gson gson2 = new GsonBuilder().excludeFieldsWithModifiers().create();