2017-01-25 5 views
0

Ich benutze fasterxml in 2.6.4 und erhalte die folgende JSON durch einen externen Dienstleister, auf die ich keinen Einfluss auf die gegebenen Ausgang haben:Deserialize flach JSON, um komplexe POJO

{ 
    "name": "dunnosName", 
    "widthValue": 46.1, 
    "heightValue": 56.1, 
    "depthValue": 66.1, 
    "unit": "mm" 
} 

und wollen es die zur Karte folgende POJOs:

public class Dunno { 
    private String name; 
    private ValueWithUnit width; 
    private ValueWithUnit height; 
    private ValueWithUnit depth; 
} 

public class ValueWithUnit { 
    private Float value; 
    private String unit; 
} 

Meine vorbehalten Mapping sollte wie folgt aussehen:

name -> Dunno.name 

widthValue -> Dunno.width.value 

heightValue -> Dunno.height.value 

depthValue -> Dunno.depth.value 

unit -> Dunno.width.unit 

unit -> Dunno.height.unit 

unit -> Dunno.depth.unit 

Ist Ist es möglich, das erwartete Mapping mit fasterxml zu realisieren? Und wenn ja, welche XML-Annotationen oder -Klassen muss ich implementieren, um dieses Mapping zu realisieren?

+0

Blick auf th nur Die Dokumente sind nicht ganz sicher, ob es möglich ist (vielleicht habe ich nicht gründlich nachgesehen). Möglicherweise müssen Sie die Antwort als Proxy verwenden und sie so transformieren, dass sie automatisch analysiert werden kann, z. B. wenn Sie jeden "Wert" so transformieren, dass er den Wert und die Einheit enthält. – Brendan

Antwort

1

Sie benötigen keine Übergangs TempDunno. Sie benötigen eine Custom Deserializer. Dies ist ein Lehrbuchbeispiel, in dem Sie eines verwenden würden. Fügen Sie die folgende Anmerkung zu Dunno Klasse:

@JsonDeserialize(using = DunnoDeserializer.class) 

und hier ist es, und mit der Eingabevalidierung auch:

@SuppressWarnings("serial") 
public class DunnoDeserializer extends StdDeserializer<Dunno> 
{ 
    public DunnoDeserializer() 
    { 
     this(null); 
    } 

    public DunnoDeserializer(Class<?> vc) 
    { 
     super(vc); 
    } 

    @Override 
    public Dunno deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException 
    { 
     Dunno dunno = new Dunno(); 
     // first parse the input into a map, which is more convenient to work with 
     @SuppressWarnings("unchecked") 
     Map<String, Object> values = jp.getCodec().readValue(jp, Map.class); 
     dunno.name = values.containsKey("name") ? values.get("name").toString() : "empty"; 
     String unit = values.containsKey("unit") ? values.get("unit").toString() : "default-units"; 
     if (values.containsKey("widthValue")) { 
      dunno.width = new ValueWithUnit(); 
      dunno.width.value = ((Number)values.get("widthValue")).floatValue(); 
      dunno.width.unit = unit; 
     } 
     if (values.containsKey("heightValue")) { 
      dunno.height = new ValueWithUnit(); 
      dunno.height.value = ((Number)values.get("heightValue")).floatValue(); 
      dunno.height.unit = unit; 
     } 
     if (values.containsKey("depthValue")) { 
      dunno.depth = new ValueWithUnit(); 
      dunno.depth.value = ((Number)values.get("depthValue")).floatValue(); 
      dunno.depth.unit = unit; 
     } 
     System.out.println(values); 
     values.values().forEach(v -> System.out.println(v.getClass())); 
     return dunno; 
    } 
} 

Testmethode:

public static void main(String[] args) 
{ 
    String jsonString = "{ \"name\": \"dunnosName\"," + "\"widthValue\": 46.1," + "\"heightValue\": 56.1," 
      + "\"depthValue\": 66.1," + "\"unit\": \"mm\"}"; 

    ObjectMapper mapper = new ObjectMapper(); 
    try { 
     Dunno d = (Dunno)mapper.readValue(jsonString, Dunno.class); 
     System.out.format("%s: %.2f(%s) %.2f(%s) %.2f(%s)", 
       d.name, d.width.value, d.width.unit, d.height.value, d.height.unit, d.depth.value, d.depth.unit); 

    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 

die Ausgabe erwartet ergibt:

dunnosName: 46.10(mm) 56.10(mm) 66.10(mm) 
+0

Die Idee ist gut, aber vorgeschlagene Lösung wird nicht genau mit den privaten Feldern arbeiten, so müssen Sie die Setter verwenden – maloney

+0

Sie erkennen, dass wir einen Beitrag von 10 Monaten diskutieren, richtig? Wie auch immer, ** NO ** Lösung funktioniert mit privaten Feldern. Das ist hier nicht das Problem. Es wird angenommen, dass Getter und Setter zur Verfügung gestellt werden. –

+0

Außerdem wurde die "vorgeschlagene" Lösung akzeptiert, also denke ich, dass es für OP funktioniert –

-1
public class Dunno { 
    private String name; 
    private ValueWithUnit width; 
    private ValueWithUnit height; 
    private ValueWithUnit depth; 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    public ValueWithUnit getWidth() { 
     return width; 
    } 

    public void setWidth(ValueWithUnit width) { 
     this.width = width; 
    } 

    public ValueWithUnit getHeight() { 
     return height; 
    } 

    public void setHeight(ValueWithUnit height) { 
     this.height = height; 
    } 

    public ValueWithUnit getDepth() { 
     return depth; 
    } 

    public void setDepth(ValueWithUnit depth) { 
     this.depth = depth; 
    } 

    @Override 
    public String toString() { 
     return "Dunno{" + 
       "name='" + name + '\'' + 
       ", width=" + width + 
       ", height=" + height + 
       ", depth=" + depth + 
       '}'; 
    } 
} 

public class ValueWithUnit { 
    private Float value; 
    private String unit; 

    public ValueWithUnit(Float value, String unit) { 
     this.value = value; 
     this.unit = unit; 
    } 

    public Float getValue() { 
     return value; 
    } 

    public void setValue(Float value) { 
     this.value = value; 
    } 

    public String getUnit() { 
     return unit; 
    } 

    public void setUnit(String unit) { 
     this.unit = unit; 
    } 

    @Override 
    public String toString() { 
     return "ValueWithUnit{" + 
       "value=" + value + 
       ", unit='" + unit + '\'' + 
       '}'; 
    } 
} 

public class TempDunno { 
    private String name; 
    private Float widthValue; 
    private Float heightValue; 
    private Float depthValue; 
    private String unit; 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    public Float getWidthValue() { 
     return widthValue; 
    } 

    public void setWidthValue(Float widthValue) { 
     this.widthValue = widthValue; 
    } 

    public Float getHeightValue() { 
     return heightValue; 
    } 

    public void setHeightValue(Float heightValue) { 
     this.heightValue = heightValue; 
    } 

    public Float getDepthValue() { 
     return depthValue; 
    } 

    public void setDepthValue(Float depthValue) { 
     this.depthValue = depthValue; 
    } 

    public String getUnit() { 
     return unit; 
    } 

    public void setUnit(String unit) { 
     this.unit = unit; 
    } 

    @Override 
    public String toString() { 
     return "TempDunno{" + 
       "name='" + name + '\'' + 
       ", widthValue=" + widthValue + 
       ", heightValue=" + heightValue + 
       ", depthValue=" + depthValue + 
       ", unit='" + unit + '\'' + 
       '}'; 
    } 
} 

public class Main { 

    public static void main(String[] args) throws IOException { 
     String json = "{\n" + 
       "  \"name\": \"dunnosName\",\n" + 
       "  \"widthValue\": 46.1,\n" + 
       "  \"heightValue\": 56.1,\n" + 
       "  \"depthValue\": 66.1,\n" + 
       "  \"unit\": \"mm\"\n" + 
       "}"; 

     System.out.println(getDunno(json)); 
    } 

    private static Dunno getDunno(String json) throws IOException { 
     ObjectMapper mapper = new ObjectMapper(); 
     TempDunno tmp = mapper.readValue(json, TempDunno.class); 
     Dunno dunno = new Dunno(); 
     dunno.setName(tmp.getName()); 
     dunno.setHeight(new ValueWithUnit(tmp.getHeightValue(), tmp.getUnit())); 
     dunno.setWidth(new ValueWithUnit(tmp.getWidthValue(), tmp.getUnit())); 
     dunno.setDepth(new ValueWithUnit(tmp.getDepthValue(), tmp.getUnit())); 
     return dunno; 
    } 
}