2

単純な文字列型のフィールドと 1 つのマップのみを持つクラスがあります。


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

私の要件は、fieldName から fieldValue (Map) へのマップを作成することですが、fieldNames は Myclass のフィールド名ではなく @SerializedName と同じにする必要があります。MyClass のような複雑な型の場合、低レベルの逆シリアル化を自分で行う必要がある場合があることに気付きました。誰かがこれに出くわしましたか?

4

2 に答える 2

0

(質問は、Gsonを使用してJSONマップ構造をJavaに逆シリアル化する方法に関するものであることを理解していると思いますMap。)

MapGsonは現在、元の質問の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カスタムの逆シリアル化処理を実装する必要があります。(これは、宣言されたJava型が単純な場合、残念ながらGsonが現在JSONプリミティブのJava値またはプリミティブ型を自動的に生成しない状況です。したがって、カスタム逆シリアル化を実装する必要があります。)StringObject

これがそのような例の1つです。

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 に答える
0

ライブラリを使用する場合は、低レベルの作業を行う必要はありませ

私は(まだ)それを使用していませんが、ジャクソンはあなたが必要とすることをするように見えます。

@SerializedNameJacksonは、必要なことを正確に実行する独自の注釈のスイートを提供しているため、その注釈を使用する必要がない場合は特に簡単です-(@JsonProperty注釈を参照)。

ジャクソンツリーモデルの操作モードを使用する場合は、探しているマップベースの結果のようなものが得られるはずです。

于 2011-03-29T00:24:37.117 に答える