JSON consumer of polymorphic objects

前端 未结 2 503
一生所求
一生所求 2020-11-27 08:56

I am parsing JSON and am having difficulty with one structure that can have one of three forms. In my case it could be zero-dimensional, one-dimensional or two-dimensional.

相关标签:
2条回答
  • 2020-11-27 09:04

    Thanks to Eric's comment pointing me to programmerbruce I managed to crack it. Here's the code I used (cut down to simplify).

    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);
      }
    }
    

    And to install this in the 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);
    
    0 讨论(0)
  • 2020-11-27 09:10

    Is this structure what you want for AClass?

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

    All you need to do is change the length of the dimensions list to account for the three types.

    Parsing becomes a trivial problem of checking if the Dimensions property is present in the JSON, and if so, iterating over it and appending to the dimensions list.


    Another idea would be to restructure the JSON (if you can) such that all cases are of the same form:

    "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" ]
        }
    }
    
    0 讨论(0)
提交回复
热议问题