如何制作反序列化 json 字符串的 fieldName 到 fieldValue 映射

发布于 2024-10-08 13:19:25 字数 300 浏览 1 评论 0原文

我有一个类,只有简单的字符串类型字段和一个映射:


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

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

I have a class having trivial string typed fields and one map only:


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

My requirement is to create a map of fieldName to fieldValue (Map) but the fieldNames should be the same as @SerializedName rather than Myclass's field name. I realize that for a complex type like MyClass I may have to do some low-level deserialization myself. Has anyone come across this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

苏别ゝ 2024-10-15 13:19:25

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

我还没有使用过它,但是 Jackson 看起来它可以满足您的需要。

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

如果您使用 杰克逊树模型 操作模式,您应该得到类似基于地图的结果正在寻找。

If you use a library, you shouldn't need to do any low-level work.

I haven't used it (yet) but Jackson looks like it'll do what you need.

It would be especially easy if you're not required to use that @SerializedName annotation, as Jackson provides a suite of its own annotations which do exactly what you need - (see the @JsonProperty annotation).

If you use the Jackson Tree Model mode of operation, you should get something like the map-based results you're looking for.

允世 2024-10-15 13:19:25

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

Gson 目前需要更多有关 Map 的类型信息> 比原始问题中提供的 Java 类结构。不要声明 randomDetails 是一个普通的旧 Map,而是让 Gson 知道它是一个 Map。然后,以下示例 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,或者 randomDetails 必须是普通的旧 Map,没有其他类型信息,那么有必要实现自定义反序列化处理,如中所述用户指南。 (不幸的是,如果声明的 Java 类型只是 Object,Gson 当前不会自动从 JSON 基元自动生成 String 或基元类型的 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;
}

(I think I understand that the question concerns how to use Gson to deserialize a JSON map structure to a Java Map.)

Gson currently needs a little bit more type information about the Map than the Java class structure in the original question provides. Instead of declaring that randomDetails is a plain old Map, let Gson know that it's a Map<String, String>. Then, the following example JSON and simple deserialization code runs as expected.

input.json Contents:

{
  "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;
}

Note that this converts all values in the Map into Strings. If you wanted something more generic, like a Map<String, Object>, or if randomDetails must be a plain old Map without additional type information, then it's necessary to implement custom deserialization processing, as described in the user guide. (This is a situation where Gson unfortunately does not currently automatically generate Java values of String or primitive type from JSON primitives, if the declared Java type is simply Object. Thus it's necessary to implement the custom deserialization.)

Here's one such example.

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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文