我想使用GSON将我的Example类下面的序列化为
JSON.
import com.google.gson.Gson; import com.google.gson.GsonBuilder; import java.util.LinkedHashMap; public class Example { private LinkedHashMap<String,Object> General; private static final String VERSION="Version"; private static final String RANGE="Range"; private static final String START_TIME="Start_Time"; private static final String END_TIME="End_Time"; public Example() { General = new LinkedHashMap<String,Object>(); General.put(VERSION,"0.1"); LinkedHashMap<String,String> Range = new LinkedHashMap<String,String>(); Range.put(START_TIME,"now"); Range.put(END_TIME,"never"); General.put(RANGE,Range); } public String toJSON() { Gson gson = new GsonBuilder().serializeNulls().create(); return gson.toJson(this); } }
我预计会得到以下输出:
{"General":{"Version":"0.1","Range":{"Start_Time":"now","End_Time":"never"}}}
{"General":{"Version":"0.1","Range":{}}}
似乎GSON无法序列化Map General中的Map Range.这是GSON的限制还是我在这里做错了?
解决方法
Nishant’s answer的原因是因为Gson的默认构造函数可以使用默认的所有类型的东西,否则您将手动可以使用GsonBuilder.
从JavaDocs:
Constructs a Gson object with default configuration. The default configuration has the following settings:
- The JSON generated by toJson methods is in compact representation. This means that all the unneeded white-space is removed. You can change this behavior with GsonBuilder.setPrettyPrinting().
- The generated JSON omits all the fields that are null. Note that nulls in arrays are kept as is since an array is an ordered list. Moreover,if a field is not null,but its generated JSON is empty,the field is kept. You can configure Gson to serialize null values by setting GsonBuilder.serializeNulls().
- Gson provides default serialization and deserialization for Enums,Map,java.net.URL,java.net.URI,java.util.Locale,java.util.Date,java.math.BigDecimal,and java.math.BigInteger classes. If you would prefer to change the default representation,you can do so by registering a type adapter through GsonBuilder.registerTypeAdapter(Type,Object).
- The default Date format is same as java.text.DateFormat.DEFAULT. This format ignores the millisecond portion of the date during serialization. You can change this by invoking GsonBuilder.setDateFormat(int) or GsonBuilder.setDateFormat(String).
- By default,Gson ignores the com.google.gson.annotations.Expose annotation. You can enable Gson to serialize/deserialize only those fields marked with this annotation through GsonBuilder.excludeFieldsWithoutExposeAnnotation().
- By default,Gson ignores the com.google.gson.annotations.Since annotation. You can enable Gson to use this annotation through GsonBuilder.setVersion(double).
- The default field naming policy for the output Json is same as in Java. So,a Java class field versionNumber will be output as “versionNumber@quot; in Json. The same rules are applied for mapping incoming Json to the Java classes. You can change this policy through GsonBuilder.setFieldNamingPolicy(FieldNamingPolicy).
- By default,Gson excludes transient or static fields from consideration for serialization and deserialization. You can change this behavior through GsonBuilder.excludeFieldsWithModifiers(int).
好的,现在我看看是什么问题.默认的Map序列化程序,如您所料,不支持嵌套映射.正如你在this source snippet from DefaultTypeAdapters中看到的那样(特别是如果你使用一个调试器),变量childGenericType被设置为java.lang.Object类型,因为一些神秘的原因,所以值的运行时类型永远不会被分析.
两个解决方案,我猜:
> Implement your own Map serializer / deserializer
>使用更复杂的方法,如下所示:
public String toJSON(){ final Gson gson = new Gson(); final JsonElement jsonTree = gson.toJsonTree(General,Map.class); final JsonObject jsonObject = new JsonObject(); jsonObject.add("General",jsonTree); return jsonObject.toString(); }