1

我已阅读 Gson 文档并决定使用它。但我不知道如何为一个字段设置两个不同的 JSON 键。例如,我有:

public class Box {

  @SerializedName("w")
  private int width;

  @SerializedName("h")
  private int height;

  @SerializedName("d")
  private int depth;

}

对于 field ,如果在 JSON 字符串中找不到 first width,我想用 keyw或 Alternative key反序列化它。width

例如,{"width":3, "h":4, "d":2}或者{"w":3, "h":4, "d":2}应该可以解析为 Box 类。

我怎样才能使用注释或使用TypedAdapter?

4

2 回答 2

1

一种解决方案可能是这样写TypeAdapter

package stackoverflow.questions.q19332412;

import java.io.IOException;

import com.google.gson.TypeAdapter;
import com.google.gson.stream.*;

public class BoxAdapter extends TypeAdapter<Box>
{

    @Override
    public void write(JsonWriter out, Box box) throws IOException {
        out.beginObject();
        out.name("w");
        out.value(box.width);
        out.name("d");
        out.value(box.depth);
        out.name("h");
        out.value(box.height);
        out.endObject();
    }

    @Override
    public Box read(JsonReader in) throws IOException {
        if (in.peek() == JsonToken.NULL) {
            in.nextNull();
            return null;
          }
        
        in.beginObject();
        Box box = new Box();
        while (in.peek() == JsonToken.NAME){
            String str = in.nextName();
            fillField(in, box, str);
        }
            
        in.endObject();
        return box;
    }

    private void fillField(JsonReader in, Box box, String str)
            throws IOException {
        switch(str){
            case "w": 
            case "width": 
                box.width = in.nextInt();
            break;
            case "h":
            case "height": 
                box.height = in.nextInt();
            break;
            case "d": 
            case "depth":
                box.depth = in.nextInt();
            break;
        }
    }
}

注意放入BoxBoxAdapter放入同一个包中。我将Box字段的可见性更改为包可见以避免使用 getter/setter。但如果你愿意,你可以使用 getter/setter。

这是调用代码:

package stackoverflow.questions.q19332412;

import com.google.gson.*;

public class Q19332412 {

    /**
     * @param args
     */
    public static void main(String[] args) {
        String j1 = "{\"width\":4, \"height\":5, \"depth\"=1}";
        String j2 = "{\"w\":4, \"h\":5, \"d\"=1}";
        
        GsonBuilder gb = new GsonBuilder().registerTypeAdapter(Box.class, new BoxAdapter());
        Gson g = gb.create();
        System.out.println(g.fromJson(j1, Box.class));
        System.out.println(g.fromJson(j2, Box.class));
    }

}

这是结果:

框[宽度=4,高度=5,深度=1]

框[宽度=4,高度=5,深度=1]

于 2013-10-12T10:16:25.810 回答
1

更新:

@SerializedName在注释中可以实现与alternate名称相同的功能。

class Box {

    @SerializedName("w", alternate = ["width"])
    private val width: Int = 0

    @SerializedName("h", alternate = ["height"])
    private val height: Int = 0

    @SerializedName("d")
    private val depth: Int = 0
}
于 2018-09-03T05:47:35.473 回答