This project implements some useful features missing from the extremely useful Gson project
There is no attempt to modify any existing behavior or existing class of Gson. In fact, this project depends on Gson. The main objective is to extend Gson using TypeAdapter and TypeAdapterFactory instances to support more features.
All of the features can be accessed by the GsonFireBuilder
. This class will build internally a GsonBuilder
with all the desired features from which a Gson
instance can be obtained.
Ability to alter a JsonElement before it is converted into an object.
GsonFireBuilder builder = new GsonFireBuilder()
.registerPreProcessor(SomeClass.class, new PreProcessor<SomeClass>() {
@Override
public void preDeserialize(Class<? extends A> clazz, JsonElement src, Gson gson) {
//Here you can add logic to change the src object before it gets converted into the Class clazz
}
});
Gson gson = builder.createGson();
Ability to alter a JsonElement after it has been generated from an object.
GsonFireBuilder builder = new GsonFireBuilder()
.registerPostProcessor(SomeClass.class, new PostProcessor<SomeClass>() {
@Override
public void postDeserialize(SomeClass result, JsonElement src) {
//Here you can add logic to change the SomeClass instance
}
@Override
public void postSerialize(JsonElement result, SomeClass src) {
//Here you can inject new fields into the result JsonElement
}
});
Gson gson = builder.createGson();
Useful when you have a base class and some sub-classes and you need to de-serialize some json into one of the sub-classes. The sub-class type will be determined by a field on the json.
GsonFireBuilder builder = new GsonFireBuilder()
.registerTypeSelector(Base.class, new TypeSelector<Base>() {
@Override
public Class<? extends Base> getClassForElement(JsonElement readElement) {
String kind = readElement.getAsJsonObject().get("kind").getAsString();
if(kind.equals("a")){
return A.class; //This will cause Gson to deserialize the json mapping to A
} else if(kind.equals("b")) {
return B.class; //This will cause Gson to deserialize the json mapping to B
} else {
return null; //returning null will trigger Gson's default behavior
}
}
});
Gson gson = builder.createGson();
You can annotate methods to be automatically evaluated and serialized
public void SomeClass{
@ExposeMethodResult("name")
public String getName(){
return "a";
}
}
//Then
GsonFireBuilder builder = new GsonFireBuilder()
.enableExposeMethodResult(); //This will make Gson to evaluate and
//serialize all methods annotated with @ExposeMethodResult
You can use GsonFireBuilder.addSerializationExclusionStrategy
if you want to add custom exclusion strategies for
some methods.
Dates can be serialized either to a unix epoch with or without milliseconds. Also RFC3339 is supported
GsonFireBuilder builder = new GsonFireBuilder();
//then
builder.dateSerializationPolicy(DateSerializationPolicy.unixTimeMillis);
//or
builder.dateSerializationPolicy(DateSerializationPolicy.unixTimeSeconds);
//or
builder.dateSerializationPolicy(DateSerializationPolicy.rfc3339); //date and time will be serialized
//or
builder.dateSerializationPolicy(DateSerializationPolicy.rfc3339Date); //only date portion will be serialized
If no policy is specified, the default Gson behavior will be used
Some special annotated methods will be invoked in your java object before serializing and after deserializing
public void SomeClass{
@PreSerialize
public void preSerializeLogic(){
//this method will get invoked just before
//the class is serialized to gson
}
@PostDeserialize
public void postDeserializeLogic(){
//this method will get invoked just after
//the class is instantiated from a json
//NOTE: this gets invoked before the PostProcessors
}
}
//Later
Gson builder = new GsonFireBuilder()
.enableHooks(SomeClass.class);
Gson gson = builder.createGson();
Any Exception
thrown inside the hooks will be wrapped into a HookInvocationException
By default Gson does not serializes Iterable
implementations. Gson on Fire provides a wrapper class called
SimpleIterable
that allows full serialization an deserialization of Iterables.
Serialization
Gson gson = new GsonFireBuilder().createGson();
SimpleIterable<Integer> simpleIterable = SimpleIterable.of(anotherIterable);
String json = gson.toJson(simpleIterable) //this will serialize the contents of "anotherIterable" as a json array
De-serialization
Gson gson = new GsonFireBuilder().createGson();
SimpleIterable<Integer> simpleIterable = gson.fromJson("[1,2,3]", new TypeToken<SimpleIterable<Integer>>(){}.getType());
//Now simpleIterable allows to iterate on the three integer values
for(Integer i: simpleIterable) {
///...
}
Gson allows to define custom exclusion strategies for fields. However it is not possible to exclude a field depending on the value that it contains. This is the way to do it with Gson on Fire:
public class SomeClass {
@ExcludeByValue(ExcludeLogic.class)
private String someField;
}
public class ExcludeLogic implements ExclusionByValueStrategy<String> {
@Override
public boolean shouldSkipField(String fieldValue) {
//some custom condition
}
}
Then you need to enable exclusion by value on Gson on Fire:
Gson builder = new GsonFireBuilder()
.enableExclusionByValue();
Gson gson = builder.createGson();
Ability to wrap a class with a string after serialization and unwrap that class before deserialization. This is useful when you write JSON objects and need to specify the name of the class to deserialize.
public class MyClass {
@Expose
public String field;
}
It is necessary to specify a Mapper or a String:
GsonFireBuilder gsonFireBuilder = new GsonFireBuilder()
.wrap(MyClass.class, new Mapper<MyClass, String>() {
@Override
public String map(MyClass myClass) {
return "myClass";
}
});
GsonFireBuilder gsonFireBuilder = new GsonFireBuilder()
.wrap(MyClass.class, "myClass");
The previous code will serialize to / deserialize from:
{
myClass: {
field: "v1"
}
}
instead of
{
field: "v1"
}
Allows you to define default values when parsing an enum in case the string representation does not map to any of the enum values
Imagine this Enum:
public enum MyEnum {
one, two, three, other
}
And this Gson instance:
Gson gson = new GsonFireBuilder()
.softEnum(MyEnum.class, MyEnum.other)
.createGson();
If you try to parse, for example, the string "four"
as the type MyEnum
, instead of getting null
, it will be parsed as the MyEnum.other
Makes it easy to build json elements without using temporary variables to store them
The following code:
JsonObject builtObject = new JsonObjectBuilder()
.set("name", "Company, inc")
.set("offices", new JsonArrayBuilder()
.add(new JsonObjectBuilder()
.set("zip", 10001)
.set("name", "Manhattan")
)
.add(new JsonObjectBuilder()
.set("zip", 11214)
.set("name", "Brooklyn")
)
).build();
Produces the following json:
{
"name": "Company, inc",
"offices": [
{
"zip": 10001,
"name": "Manhattan"
},
{
"zip": 11214,
"name": "Brooklyn"
}
]
}
To access the good old GsonBuilder:
GsonFireBuilder fireBuilder = new GsonFireBuilder();
// Here you can configure the fireBuilder however you want
// and then request a GsonBuilder. The GsonBuilder will be pre-configured
// with all the GsonFire features.
GsonBuilder gsonBuilder = fireBuilder.createGsonBuilder();
// Here you can customize the gsonBuilder using the Gson features and
// then create a Gson object
Gson gson = gsonBuilder.create()
//The resulting Gson object will have all the GsonFire and Gson features
- Fixes #49. Fraction of second incorrect writing. Thanks jpedrofigueiredo for the contribution!
- Fixes #40. Fraction of second incorrect parsing. Thanks @crystalin
- Adds OSGi support #44. Thanks @abangerl
- Fixes #39. The
JsonTreeReader
andJsonTreeWriter
used for the Pre/Post processors was not properly set up to mimic the originalJsonReader
orJsonWriter
. Thanks @daw3rd
- Fixes #34. Hooks were not correctly bubbling up
Exceptions
, but instead they were printing and swallowing 🍔 them. Thanks @Xyaren
- Fixes a bug in which GsonFire was not honoring the "lenient" flag from the
GsonBuilder
. Thanks @Groostav
- Reusing the instances of
ExclusionByValueStrategy
instead of creating an instance each time it is used. Thanks @Frotty - Fix the use of a type selector was preventing the GsonFire featues to be executed on the selected type. Thanks a-a-davydov and @rubioz
- Breaking change: softParse was renamed to enumDefaultValue
- enumDefaultValue now just decorates Gson's internal enum support
- Fix: Soft parsing of enums was breaking when the enums had null values
- New feature: Soft parsing of Enums! Thanks @rubioz for the idea!
- New feature: wrap/unwrap json objects automatically. Thanks @andressanchez!
- New feature: Adds builders for JsonObject and JsonArray
- Using Gson 2.7
- Using the new available Gson.getFieldNamingStrategy method instead of reflection
- Fixed a bug in which NullPointerExceptions were thrown when using hooks #25. Thanks @knezmilos13
- Fixed a bug that caused the RFC3339 date serializing not to be thread safe #24. Thanks @npanasenko.
- Hook methods now can get injected the source
JsonElement
andGson
objects #23. Thanks @molexx.
- Fixed a bug in which pre-processors could run multiple times when used in conjunction with TypeSelectors.
- Adds support for RFC3339 date (without the time portion). Thanks @WonderCsabo
- TypeSelectors will now be invoked also on sub-classes of the class they are registered for. Thanks @iwarapter
- Fixed a
NullPointerException
that could happen when using the exclude by value feature (thanks @joaocpsantos)
- Adds the ability to exclude fields depending on its value (thanks @joaocpsantos)
- Optimized the way objects are explored with reflection
- Adds non-anonymous
Iterable
calledSimpleIterable
that can be serialized and de-serialized.
- Adds
GsonFireBuilder.addSerializationExclusionStrategy
(thanks @lalpert)
- Renames project package to
io.gsonfire
- Gson on Fire is now at Maven Central
- Deprecates the Merge Map functionality in favor of Post Processors
- Fixes a bug in which GsonFire was not running the type adapters in the same order as class hierarchy.
- Adds Pre Processors!
Gson on Fire is now at Maven Central. This means that there is no need to add the extra maven repository anymore.
Add to your pom.xml
<dependencies>
<dependency>
<groupId>io.gsonfire</groupId>
<artifactId>gson-fire</artifactId>
<version>1.9.0</version>
</dependency>
</dependencies>
Add to your build.gradle
dependencies {
compile 'io.gsonfire:gson-fire:1.9.0'
}
Bitcoin Address: 14LFRrMX3HmyAH9zQsnzYoVKDH6bVWiBu3