【问题标题】:Generic POJO for JSON Object that can take different type of values可以采用不同类型值的 JSON 对象的通用 POJO
【发布时间】:2020-06-05 03:08:07
【问题描述】:

我有一个带有已定义架构的 json 有效负载(rest api 的请求有效负载),但有一个属性可以采用一组未知键值对。每个属性的值可以是不同的类型,如数字、字符串、数组、范围、日期等。如何为该属性创建 POJO 并使反序列化工作相同?

我目前正在考虑为我的 Property 类编写一个自定义反序列化器,在其中我检查值的类型并相应地执行一些自定义逻辑。

这看起来是一个典型的要求。我觉得 Jackson 或 Gson 中应该有一些我想念的东西。如果它已经存在,我很乐意重用。我在 SO 中环顾四周,但到目前为止找不到一个好的答案。任何建议将不胜感激。

{
  "id": 1234,
  "name": "test name 1",
  "properties": [
    {
      "key_a": 100
    },
    {
      "key_b": [
        "string1",
        "string2",
        "string3"
      ]
    },
    {
      "key_c": {
        "range": {
          "min": 100,
          "max": 1000
        }
      }
    }
  ]
}

我认为我的属性对象的 POJO 看起来像这样。

class Property {
   private String key;
   private Value value; 
}

【问题讨论】:

  • 一种简单的方法是将其反序列化为List<Map<Stirng, Object>>
  • Value的结构是什么?

标签: java json jackson gson json-deserialization


【解决方案1】:

可以使用继承。这是杰克逊示例的课程

public class Sample {

    @JsonProperty(value = "id")
    Integer id;
    @JsonProperty(value = "name")
    String name;
    @JsonProperty(value = "properties")
    List<Property> properties;
}


@JsonTypeInfo(
        use = JsonTypeInfo.Id.NAME,
        include = JsonTypeInfo.As.WRAPPER_OBJECT)
@JsonSubTypes({
        @JsonSubTypes.Type(value = KeyA.class, name = "key_a"),
        @JsonSubTypes.Type(value = KeyB.class, name = "key_b"),
        @JsonSubTypes.Type(value = KeyC.class, name = "key_c")
})
public abstract class Property {
}

public class KeyA extends Property{
    Integer value;

    public KeyA(Integer value) {
        this.value = value;
    }
    @JsonValue
    public Integer getValue() {
        return value;
    }
}

public class KeyB  extends Property {

    List<String> valueList;


    @JsonCreator
    public KeyB( List<String> valueList) {
        this.valueList = valueList;
    }

    @JsonValue
    public List<String> getValueList() {
        return valueList;
    }

}

public class KeyC  extends Property {
   @JsonProperty(value = "range")
    Range value;

}

public class Range {
    @JsonProperty(value = "min")
    Integer min;
    @JsonProperty(value = "max")
    Integer max;
}

【讨论】:

  • 我不想为每个键和值创建 POJO。特别是这些值可以是不同的类型,如数组、数字、范围对象或任何其他自定义对象。
【解决方案2】:

如果我理解正确,您想更改为 JSON 并返回。我为自己的 SpringBoot 项目写了一个小类,使用 ObjectMapper

@Component
public final class JsonUtils {

    private final ObjectMapper mapper;

    @Autowired
    public JsonUtils(ObjectMapper mapper) {
        this.mapper = mapper;
    }

    public String asJsonString(final Object object) {
        try {
            return mapper.registerModule(new JavaTimeModule())
                    .writeValueAsString(object);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /*
     * Customized Objectmapper for reading values compatible with this class' other methods
     * @Return the desired object you want from a JSON
     * IMPORTANT! -your return object should be a class that has a @NoArgsConstructor-
     */
    public Object readValue(final String input, final Class<?> classToRead) {
        try {
            return mapper
                    .readValue(input, classToRead);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}`

也许它对你有用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-07-14
    • 2015-09-04
    • 1970-01-01
    • 1970-01-01
    • 2020-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多