GSon property allow primitive or composite mapping

柔情痞子 提交于 2020-02-07 17:12:33

问题


I want to create the following json from my model

either i have

{"name" : "Arsénio", "value" : 12}

or

{"name" : "Arsénio", "value" : {"min" : 12, "max" : 100, "value" : 200}}

I've defined the following POJO's

class Data {
  String name;
  Value value;
}

abstract class Value {}

class IntegerValue : Value { 
int value;
}

class RangeValue : Value {
    int max, min, value;
}

Obviously this won't output my required json for the first case when using IntegerValue since it will output

Gson gson = new Gson();

Data data = new Data();
data.name = "Arsénio";
data.value = new IntegerValue();
data.value.value = 12;

String result = gson.toJson(data, Data.class);

System.out.println(result);

Output:

{"name": "Arsénio", "value" : {"value" : 12}}

Whats the correct way to model my POJO's in this case ?


回答1:


I have managed to solve by using an type adapter for the IntegerValue not sure if this is the correct and simpler solution so i will wait a while before accept my own answer.

Gson gson = new GsonBuilder()
                .registerTypeAdapter(IntValue.class, new IntegerValueTypeAdapter())
                .create();
public class IntValueTypeAdapter extends TypeAdapter<IntegerValue> {

@Override
public void write(JsonWriter out, IntegerValue value) throws IOException {
    out.value(value.value);
}


@Override
public IntegerValue read(JsonReader in) throws IOException {
    // do something similar, but the other way around
    throw new UnsupportedOperationException("deserialize not supported for IntegerValue");
}

}




回答2:


You can write a custom TypeAdapter:

public class ValueTypeAdapter extends TypeAdapter<Value> {

    @Override
    public Value read(JsonReader in) throws IOException {

        Value value = null;

        JsonParser jsonParser = new JsonParser();
        JsonElement je = jsonParser.parse(in);

        if (je instanceof JsonPrimitive) {
            value = new Value();
            value.value = ((JsonPrimitive) je).getAsInt();
        } else if (je instanceof JsonObject) {
            JsonObject jsonObject = (JsonObject) je;
            value = new Value();
            value.max = jsonObject.get("max").getAsInt();
            value.min = jsonObject.get("min").getAsInt();
            value.value = jsonObject.get("value").getAsInt();
        }

        return value;
    }

    @Override
    public void write(JsonWriter out, Value value) throws IOException {
        if (value != null) {
            if (value.min == 0 && value.max == 0) {
                out.value(value.value);
            } else {
                out.beginObject();

                out.name("min").value(value.min);
                out.name("max").value(value.max);
                out.name("value").value(value.value);

                out.endObject();
            }
        }
    }
}

Your POJO Classes:

public static class Data {
    String name;
    Value value;
}

public static class Value {
    int max, min, value;
}

Test:

    String json0 = "{\"name\" : \"Arsénio\", \"value\" : 12}";
    String json1 = "{\"name\" : \"Arsénio\", \"value\" : {\"min\" : 12, \"max\" : 100, \"value\" : 200}}";

    GsonBuilder gsonBuilder = new GsonBuilder();
    gsonBuilder.registerTypeAdapter(Value.class, new ValueTypeAdapter());
    Gson gson = gsonBuilder.create();

    // 1) Deserialize json to java instances
    Data data0 = gson.fromJson(json0, Data.class);
    Data data1 = gson.fromJson(json1, Data.class);

    // 2) Serialize json to java instances to see your incoming json string equals to seriallize one 
    String serialized0 = gson.toJson(data0);
    String serialized1 = gson.toJson(data1);

    System.out.println("serialized0:" + serialized0);
    System.out.println("serialized1:" + serialized1);


来源:https://stackoverflow.com/questions/26761541/gson-property-allow-primitive-or-composite-mapping

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!