2

我有一个类有简单的字符串类型字段和一个地图:


class MyClass {
  @SerializedName("handle");
  String nickName;
  Map randomDetails;
} 

我的要求是创建 fieldName 到 fieldValue (Map) 的映射,但 fieldNames 应该与 @SerializedName 相同,而不是 Myclass 的字段名称。我意识到对于像 MyClass 这样的复杂类型,我可能必须自己进行一些低级反序列化。有没有人遇到过这个?

4

2 回答 2

0

如果您使用库,则不需要做任何低级工作。

我还没有使用它(还),但杰克逊看起来它会做你需要的。

如果您不需要使用该@SerializedName注释,那将特别容易,因为 Jackson 提供了一套自己的注释,可以完全满足您的需求 - (请参阅@JsonProperty注释)。

如果您使用Jackson Tree Model操作模式,您应该会得到类似于您正在寻找的基于地图的结果。

于 2011-03-29T00:24:37.117 回答
0

(我想我理解这个问题涉及如何使用 Gson 将 JSON 映射结构反序列化为 Java Map。)

MapGson 目前需要比原始问题中的 Java 类结构提供的更多类型信息。不要声明这randomDetails是一个普通的 old 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;
}

请注意,这会将 in 中的所有值转换MapStrings. 如果你想要更通用的东西,比如 a Map<String, Object>,或者如果randomDetails必须是一个普通的旧的Map没有额外的类型信息,那么有必要实现自定义反序列化处理,如用户指南中所述String(不幸的是,如果声明的 Java 类型是简单的,则Gson 目前不会自动从 JSON 基元生成 Java 值或基元类型Object。因此,有必要实现自定义反序列化。)

这是一个这样的例子。

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;
}
于 2011-06-10T00:56:03.007 回答