4

我正在解析 JSON,并且在使用一种可以具有三种形式之一的结构时遇到了困难。就我而言,它可能是零维、一维或二维。有什么方法可以即时检查 JSON 以确定它是哪一个?或者也许无论如何都要消费它,然后弄清楚它是什么。

这些结构看起来像这样,可以嵌入到其他结构中。

"details":{
    "Product":"A zero-dimensional Product"
},

"details":{
    "Product":"A one-dimensional Product",
    "Dimensions": [ "Size" ],
    "Labels": [ "XS", "S", "M", "L" ]
},

"details":{
    "Product":"A two-dimensional Product",
    "Dimensions": [ "Size", "Fit" ],
    "Labels": [[ "XS", "S", "M", "L" ],[ "26", "28", "30", "32" ]]
}

我可能正在寻找的是杰克逊将始终与之匹配的通用类。

类似于翻译的东西:

{
"SomeField": "SomeValue",
...
 "details":{
  ...
 }
}

进入:

class MyClass {
  String SomeField;
  ...
  AClass details;
}

AClass我可以定义一个可以作为任何 JSON 结构或数组的通用接收者的类吗?

4

2 回答 2

5

感谢 Eric 将我指向程序员布鲁斯的评论,我设法破解了它。这是我使用的代码(为了简化而删减)。

public static class Info {
  @JsonProperty("Product")
  public String product;
  // Empty in the 0d version, One entry in the 1d version, two entries in the 2d version.
  @JsonProperty("Dimensions")
  public String[] dimensions;

}

public static class Info0d extends Info {
}

public static class Info1d extends Info {
  @JsonProperty("Labels")
  public String[] labels;
}

public static class Info2d extends Info {
  @JsonProperty("Labels")
  public String[][] labels;
}

public static class InfoDeserializer extends StdDeserializer<Info> {
  public InfoDeserializer() {
    super(Info.class);
  }

  @Override
  public Info deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
    Class<? extends Info> variantInfoClass = null;
    ObjectMapper mapper = (ObjectMapper) jp.getCodec();
    ObjectNode root = (ObjectNode) mapper.readTree(jp);
    // Inspect the `diemnsions` field to decide what to expect.
    JsonNode dimensions = root.get("Dimensions");
    if ( dimensions == null ) {
      variantInfoClass = Info0d.class;
    } else {
      switch ( dimensions.size() ) {
        case 1:
          variantInfoClass = Info1d.class;
          break;

        case 2:
          variantInfoClass = Info2d.class;
          break;
      }
    }
    if (variantInfoClass == null) {
      return null;
    }
    return mapper.readValue(root, variantInfoClass);
  }
}

并将其安装在ObjectMapper

// Register the special deserializer.
InfoDeserializer deserializer = new InfoDeserializer();
SimpleModule module = new SimpleModule("PolymorphicInfoDeserializerModule", new Version(1, 0, 0, null));
module.addDeserializer(Info.class, deserializer);
mapper.registerModule(module);
factory = new JsonFactory(mapper);
于 2012-09-17T12:21:57.667 回答
2

这个结构是你想要的 AClass 吗?

class Dimension {
    String name;
    List<String> possibleValues;
}

class Product {
    String name;
    List<Dimension> dimensions;
}

您需要做的就是更改dimensions列表的长度以适应这三种类型。

解析成为检查Dimensions属性是否存在于 JSON 中的一个微不足道的问题,如果存在,则对其进行迭代并附加到dimensions列表中。


另一个想法是重组 JSON(如果可以的话),使所有情况都具有相同的形式:

"d0":{
    "Product":"A zero-dimensional Product",
    "Dimensions": {}
},

"d1":{
    "Product":"A one-dimensional Product",
    "Dimensions": {
        "Size": [ "XS", "S", "M", "L" ]
    }
},

"d2":{
    "Product":"A two-dimensional Product",
    "Dimensions": {
        "Size": [ "XS", "S", "M", "L" ],
        "Fit": [ "26", "28", "30", "32" ]
    }
}
于 2012-09-16T20:32:20.633 回答