当前位置: 代码迷 >> JavaScript >> Java对象跟JSON互转换利器-Gson
  详细解决方案

Java对象跟JSON互转换利器-Gson

热度:493   发布时间:2012-10-08 19:54:56.0
Java对象和JSON互转换利器-Gson
Java对象和JSON互转换利器-Gson .
2008-07-11 09:30 3182人阅读 评论(2) 收藏 举报
Gson这个Java类库可以把Java对象转换成JSON,也可以把JSON字符串转换成一个相等的Java对象。Gson支持任意复杂Java对象包括没有源代码的对象。
Gson User Guide
Gson: A library to convert Java Objects to JSON and vice-versa
Inderjeet Singh, Joel Leitch
Overview
Gson is a Java library that can be used to convert Java Objects into their JSON representation. It can also be used to convert a JSON string to an equivalent Java object. Gson is an open-source project hosted at http://code.google.com/p/google-gson. Gson can work with arbitrary Java objects including pre-existing objects that you do not have source-code of. Goals for Gson
?Provide easy to use mechanisms like toString() and constructor (factory method) to convert Java to JSON and vice-versa
?Allow pre-existing unmodifiable objects to be converted to and from JSON
?Allow custom representations for objects
?Support arbitrarily complex objects
Using Gson
The primary class to use is Gson which you can just create by calling new Gson(). There is also a class GsonBuilder available that can be used to create a Gson instance with various settings like version control and so on. 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.
Primitives Examples
(Serialization)
Gson gson = new Gson();
gson.toJson(1);            ==> prints [1] gson.toJson("abcd");       ==> prints ["abcd"] gson.toJson(new Long(10)); ==> prints [10] int[] values = { 1 }; gson.toJson(values);       ==> prints [1] (Deserialization)
int one = gson.fromJson("[1]", int.class); Integer one = gson.fromJson("1", Integer.class); Long one = gson.fromJson("[1]", Long.class); Boolean false = gson.fromJson("[false]", Boolean.class); String str = gson.fromJson("[/"abc/"]", String.class); String anotherStr = gson.fromJson("/"abc/"", String.class);
Object Examples
class BagOfPrimitives {
  private int value1 = 1;
  private String value2 = "abc";   private transient int value3 = 3;
} (Serialization)
BagOfPrimitives obj = new BagOfPrimitives();
Gson gson = new Gson();
String json = gson.toJson(obj); 
==> json is {"value1":1,"value2":"abc"} Note that you can not serialize objects with circular references since that will result in infinite recursion. (Deserialization) BagOfPrimitives obj2 = gson.fromJson(json, BagOfPrimitives.class);   ==> obj2 is just like obj
Finer Points with Objects
?It is perfectly fine (and recommended) to use private fields
?There is no need to use any annotations to indicate a field is to be included for serialization and deserialization. All fields in the current class (and from all super classes) are included by default.
?If a field is marked transient, (by default) it is ignored and not included in the JSON serialization or deserialization.
?This implementation handles nulls correctly
?While serialization, a null field is skipped from the output
?While deserialization, a missing entry in JSON results in setting the corresponding field in the object to null
?If a field is synthetic, it is ignored and not included in JSON serialization or deserialization
?Fields corresponding to the outer classes in  inner classes, anonymous classes, and local classes are ignored and not included in serialization or deserialization
Array Examples
Gson gson = new Gson(); int[] ints = {1, 2, 3, 4, 5}; String[] strings = {"abc", "def", "ghi"}; (Serialization)
gson.toJson(ints);     ==> prints [1,2,3,4,5]

gson.toJson(strings);  ==> prints ["abc", "def", "ghi"]
(Deserialization)
int[] ints2 = gson.fromJson("[1,2,3,4,5]", int[].class); ==> ints2 will be same as ints
We also support multi-dimensional arrays, with arbitrarily complex element types
Collections Examples
Gson gson = new Gson(); Collection<Integer> ints = Lists.immutableList(1,2,3,4,5); (Serialization) String json = gson.toJson(ints); ==> json is [1,2,3,4,5] (Deserialization)
Type collectionType = new TypeToken<Collection<Integer>>(){}.getType(); Collection<Integer> ints2 = gson.fromJson(collectionType, json); ints2 is same as ints Fairly hideous: note how we define the type of collection Unfortunately, no way to get around this in Java Collections Limitations
?Can serialize collection of arbitrary objects but can not deserialize from it
?Because there is no way for the user to indicate the type of the resulting object
?While deserializing, Collection must be of a specific generic type
All of this makes sense, and is rarely a problem when following good Java coding practices
Built-in Serializers and Deserializers
Gson has built-in serializers and deserializers for commonly used classes whose default representation may be inappropriate. Here is a list of such classes:
1.java.net.URL to match it with strings like "http://code.google.com/p/google-gson/".
2.java.net.URI to match it with strings like "/p/google-gson/".
Custom Serialization and Deserialization
Sometimes default representation is not what you want. This is often the case when dealing with library classes (DateTime, etc). Gson allows you to register your own custom serializers and deserializers. This is done by defining two parts:
?Json Serialiers: Need to define custom serialization for an object
?Json Deserializers: Needed to define custom deserialization for a type
?Instance Creators: Not needed if no-args constructor is available
GsonBuilder gson = new GsonBuilder(); gson.registerTypeAdapter(MyType.class, new MySerializer());
gson.registerDeserializer(MyType.class, new MyDeserializer());
gson.registerInstanceCreator(MyType.class, new MyInstanceCreator());
Writing a Serializer
Here is an example of how to write a custom serializer for JodaTime DateTime class. private class DateTimeSerializer implements JsonSerializer<DateTime> {   public JsonElement serialize(DateTime src, Type typeOfSrc, JsonSerializationContext context);     new JsonPrimitive(src.toString());   } } Gson calls toJson() when it runs into a DateTime object during serialization.
Writing a Deserializer
Here is an example of how to write a custom deserializer for JodaTime DateTime class. private class DateTimeDeserializer implements JsonDeserializer<DateTime> {   public DateTime deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)       throws JsonParseException {     return new DateTime(json.getAsJsonPrimitive().getAsString());   } } Gson calls fromJson() when it needs to deserialize a JSON string fragment into a DateTime object Finer points with Serializers and Deserializers Often you want to register a single handler for all generic types corresponding to a raw type
?For example, suppose you have an "Id" class for Id representation/translation (i.e. an internal vs. external representation).
?Id<T> type that has same serialization for all generic types
?Essentially write out the id value
?Deserialization is very similar but not exactly the same

?Need to call "new Id(Class<T>, String)" which returns an instance of Id<T>
Gson supports registering a single handler for this. You can also register a specific handler for a specific generic type (say Id<RequiresSpecialHandling> needed special handling). The Type parameter for the toJson and fromJson contains the generic type information to help you write a single handler for all generic types corresponding to the same raw type
Writing an Instance Creator
While deserializing an Object, Gson needs to create a default instance of the class Well-behaved  classes that are meant for serialization and deserialization should have a no-argument constructor
?Doesn't matter whether public or private
Typically, Instance Creators are needed when you are dealing with a library class that does NOT define a no-argument constructor Instance Creator Example private class MoneyInstanceCreator implements InstanceCreator<Money> {
  public Money createInstance(Type type) {
    return new Money("1000000", CurrencyCode.USD);
  }
}
Type could be of a corresponding generic type
?Very useful to invoke constructors which need specific generic type information
?For example, if the Id class stores the class for which the Id is being created
Versioning Support
Multiple versions of the same object can be maintained by using @Since annotation. This annotation can be used on Classes, Fields and, in a future release, Methods.
JSON Field Naming Support
Gson supports some pre-defined field naming policies to convert the standard Java field names (i.e. camel cased names starting with lower case --- "sampleFieldNameInJava") to a Json field name (i.e. sample_field_name_in_java or SampleFieldNameInJava).  It also has an annotation based strategy to allows clients to define custom names on a per field basis.  Note, that the annotation based strategy has field name validation which will raise "Runtime" exceptions if invalid field name are provided as the annotation value. The following is an example of how to use both Gson naming policy features: private class SomeObject {   @SerializedName("custom_naming") private final String someField;   private final String someOtherField;   public SomeObject(String a, String b) {     this.someField = a;     this.someOtherField = b;   } }
SomeObject someObject = new SomeObject("first", "second");
Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE).create();
String jsonRepresentation = gson.toJson(someObject);
System.out.println(jsonRepresentation);

======== OUTPUT ========
{"custom_naming":"first","SomeOtherField":"second"}
Issues in Designing Gson
See the Gson design document for a discussion of issues we faced while designing Gson. It also include a comparison of Gson with other Java libraries that can be used for Json conversion.
Future Enhancements to Gson
For the latest list of proposed enhancements and to suggest new ones, see the Issues section under the project website.
?Support JavaBeans properties alongwith fields
?For Objects with circular dependency, need to explore an alternate strategy instead of throwing error. For example, may be print null, or an id-ref kind of thing
?More strict validation
?Clean up String serialization and deserialization and make it use a custom Serializers and Deserializers
  相关解决方案