我有一个类有简单的字符串类型字段和一个地图:
class MyClass {
@SerializedName("handle");
String nickName;
Map randomDetails;
}
我的要求是创建fieldName到fieldValue(Map)的映射,但fieldNames应该与@SerializedName相同,而不是Myclass的字段名称。我意识到对于像MyClass这样的复杂类型,我可能不得不自己做一些低级反序列化。有人遇到过这个吗?
答案 0 :(得分:0)
如果您使用库,则不需要执行任何低级别工作。
我尚未使用它(但是)Jackson看起来它会做你需要的。
如果您不需要使用@SerializedName
注释,那将非常容易,因为杰克逊提供了一套its own annotations,可以完全满足您的需求 - (请参阅@JsonProperty
注解)。
如果您使用Jackson Tree Model操作模式,您应该获得类似您正在寻找的基于地图的结果。
答案 1 :(得分:0)
(我想我明白这个问题涉及如何使用Gson将JSON地图结构反序列化为Java Map
。)
Gson目前需要更多关于Map
的类型信息,而不是原始问题中提供的Java类结构。不要声明randomDetails
是一个普通的Map
,而是让Gson知道它是Map<String, String>
。然后,以下示例JSON和简单反序列化代码按预期运行。
input.json内容:
{
"handle":"the handle",
"random_details":{"one":1,"too":"B","3":false,"for":5.32}
}
<强> Foo.java:强>
import java.io.FileReader;
import java.util.Map;
import com.google.gson.FieldNamingPolicy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.annotations.SerializedName;
public class Foo
{
public static void main(String[] args) throws Exception
{
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES);
Gson gson = gsonBuilder.create();
MyClass myObject = gson.fromJson(new FileReader("input.json"), MyClass.class);
System.out.println(gson.toJson(myObject));
}
}
class MyClass
{
@SerializedName("handle")
String nickName;
Map<String, String> randomDetails;
}
请注意,这会将Map
中的所有值转换为Strings
。如果您想要更通用的内容,例如Map<String, Object>
,或者randomDetails
必须是普通的Map
而没有其他类型信息,那么就必须实现自定义反序列化处理,{{3} }。 (如果声明的Java类型只是String
,那么Gson目前不会自动从JSON原语自动生成Object
或原始类型的Java值。因此,有必要实现自定义反序列化。 )
这是一个这样的例子。
import java.io.FileReader;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import com.google.gson.FieldNamingPolicy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.annotations.SerializedName;
public class Foo
{
public static void main(String[] args) throws Exception
{
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES);
gsonBuilder.registerTypeAdapter(MyClass.class, new MyClassDeserializer());
Gson gson = gsonBuilder.create();
MyClass myObject = gson.fromJson(new FileReader("input.json"), MyClass.class);
System.out.println(gson.toJson(myObject));
}
}
class MyClassDeserializer implements JsonDeserializer<MyClass>
{
@Override
public MyClass deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException
{
JsonObject object = json.getAsJsonObject();
String nickName = object.get("handle").getAsString();
Set<Map.Entry<String, JsonElement>> mapEntries = object.get("random_details").getAsJsonObject().entrySet();
Map randomDetails = new HashMap(mapEntries.size());
for (Map.Entry<String, JsonElement> mapEntry : mapEntries)
{
String key = mapEntry.getKey();
Object value;
JsonPrimitive jsonPrimitive = mapEntry.getValue().getAsJsonPrimitive();
if (jsonPrimitive.isNumber()) value = jsonPrimitive.getAsNumber();
else if (jsonPrimitive.isBoolean()) value = jsonPrimitive.getAsBoolean();
else value = jsonPrimitive.getAsString();
randomDetails.put(key, value);
}
MyClass myObject = new MyClass();
myObject.nickName = nickName;
myObject.randomDetails = randomDetails;
return myObject;
}
}
class MyClass
{
@SerializedName("handle")
String nickName;
Map randomDetails;
}