2016-11-29 1 views
4

J'essaie de rendre la sortie Json de Cucumber dans un seul objet Java. Cela contient des objets imbriqués à quatre niveaux de profondeur, et j'ai du mal à le désérialiser. J'utilise actuellement Jackson, mais ouvert aux suggestions. Voici mon code JSON:Désérialise complexe JSON à Java, classes imbriquées plusieurs niveaux profonds

{ 
"line": 1, 
"elements": [ 
    { 
    "line": 3, 
    "name": "Converteren centimeters naar voeten/inches", 
    "description": "", 
    "id": "applicatie-neemt-maten-in-cm-en-converteert-ze-naar-voet/inch,-en-vice-versa;converteren-centimeters-naar-voeten/inches", 
    "type": "scenario", 
    "keyword": "Scenario", 
    "steps": [ 
     { 
     "result": { 
      "duration": 476796588, 
      "status": "passed" 
     }, 
     "line": 4, 
     "name": "maak Maten-object aan met invoer in \"centimeters\"", 
     "match": { 
      "arguments": [ 
      { 
       "val": "centimeters", 
       "offset": 37 
      } 
      ], 
      "location": "StepDefinition.maakMatenObjectAanMetInvoerIn(String)" 
     }, 
     "keyword": "Given " 
     }, 
     { 
     "result": { 
      "duration": 36319, 
      "status": "passed" 
     }, 
     "line": 5, 
     "name": "ik converteer", 
     "match": { 
      "location": "StepDefinition.converteerMaten()" 
     }, 
     "keyword": "When " 
     }, 
     { 
     "result": { 
      "duration": 49138, 
      "status": "passed" 
     }, 
     "line": 6, 
     "name": "uitvoer bevat maat in \"voeten/inches\"", 
     "match": { 
      "arguments": [ 
      { 
       "val": "voeten/inches", 
       "offset": 23 
      } 
      ], 
      "location": "StepDefinition.uitvoerBevatMaatIn(String)" 
     }, 
     "keyword": "Then " 
     } 
    ] 
    }, 
    { 
    "line": 8, 
    "name": "Converteren voeten/inches naar centimeters", 
    "description": "", 
    "id": "applicatie-neemt-maten-in-cm-en-converteert-ze-naar-voet/inch,-en-vice-versa;converteren-voeten/inches-naar-centimeters", 
    "type": "scenario", 
    "keyword": "Scenario", 
    "steps": [ 
     { 
     "result": { 
      "duration": 84175, 
      "status": "passed" 
     }, 
     "line": 9, 
     "name": "maak Maten-object aan met invoer in \"voeten/inches\"", 
     "match": { 
      "arguments": [ 
      { 
       "val": "voeten/inches", 
       "offset": 37 
      } 
      ], 
      "location": "StepDefinition.maakMatenObjectAanMetInvoerIn(String)" 
     }, 
     "keyword": "Given " 
     }, 
     { 
     "result": { 
      "duration": 23928, 
      "status": "passed" 
     }, 
     "line": 10, 
     "name": "ik converteer", 
     "match": { 
      "location": "StepDefinition.converteerMaten()" 
     }, 
     "keyword": "When " 
     }, 
     { 
     "result": { 
      "duration": 55547, 
      "status": "passed" 
     }, 
     "line": 11, 
     "name": "uitvoer bevat maat in \"centimeters\"", 
     "match": { 
      "arguments": [ 
      { 
       "val": "centimeters", 
       "offset": 23 
      } 
      ], 
      "location": "StepDefinition.uitvoerBevatMaatIn(String)" 
     }, 
     "keyword": "Then " 
     } 
    ] 
    } 
], 
"name": "Applicatie neemt maten in cm en converteert ze naar voet/inch, en vice versa", 
"description": "", 
"id": "applicatie-neemt-maten-in-cm-en-converteert-ze-naar-voet/inch,-en-vice-versa", 
"keyword": "Feature", 
"uri": "sample.feature" 
} 

J'ai essayé un certain nombre d'approches différentes. J'ai d'abord utilisé des classes internes imbriquées, mais il semblait que vous deviez les rendre statiques, ce que je craignais ne pas fonctionner car j'ai plusieurs instances du même objet dans un même objet (plusieurs "éléments" dans la racine, par exemple). Puis j'ai essayé de les mettre dans des classes séparées, avec des annotations Json. Voici où cela m'a fait (setters): en omettant

public class CucumberUitvoer { 
    private String name; 
    private String description; 
    private String id; 
    private String keyword; 
    private String uri; 
    private int line; 
    @JsonProperty("elements") 
    private List<FeatureObject> elements; 

    public CucumberUitvoer(){} 
} 

public class FeatureObject { 
    private String name; 
    private String description; 
    private String id; 
    private String type; 
    private String keyword; 
    private int line; 
    @JsonProperty("steps") 
    private List<StepObject> steps; 

    public FeatureObject() { 
    } 
} 

public class StepObject { 
    @JsonProperty("result") 
    private ResultObject result; 
    private String name; 
    private String given; 
    private String location; 
    private String keyword; 
    private int line; 
    @JsonProperty("match") 
    private MatchObject match; 

    public StepObject(){} 
} 

public class ResultObject { 
    private int duration; 
    private String status; 

    public ResultObject(){} 
} 

public class MatchObject { 
    @JsonProperty("arguments") 
    private List<ArgumentObject> arguments; 
    private String location; 

    public MatchObject(){} 
} 

public class ArgumentObject { 
    private String val; 
    private String offset; 

    public ArgumentObject(){} 
} 

Pour plus de précisions, un diagramme de classes d » here de la façon dont les travaux de nidification.

Cette solution me donne l'erreur suivante:

com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of nl.icaprojecten.TestIntegratieQuintor.JSONInterpreter.CucumberUitvoer out of START_ARRAY token 

Voici le code qui font le mappage réel:

ObjectMapper mapper = new ObjectMapper(); 
    mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 

    CucumberUitvoer obj1 = null; 
    try { 
     obj1 = mapper.readValue(json, CucumberUitvoer.class); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 

Y at-il une solution rapide à cette approche pour le faire fonctionner, ou devrait J'essaie quelque chose d'entièrement différent?

+0

Avez-vous essayé d'ajouter des accesseurs? Les champs ne sont pas publics, donc les objets ne peuvent pas être sérialisés dans ces classes. –

+1

Je pensais que seuls les setters étaient requis? Je les ai, juste omis ici pour rendre le code plus lisible. – KeizerHarm

+0

@TurbutAlin Ajout de getters n'a eu aucun effet, j'ai peur. – KeizerHarm

Répondre

2

Ok J'ai passé du temps à déboguer et à essayer de comprendre quel était le problème, et finalement, c'était quelque chose de plutôt évident.

implements Serializable 

thats la ligne I ajouté à MatchObject et travaillé.

Lorsque nous essayons de désérialiser un objet d'abord, nous devons faire ces classes implémente l'interface Serializable

+0

Ça m'a permis de faire de réels progrès, merci! Mais j'ai maintenant une nouvelle erreur: "java.lang.NoSuchMethodError: com.fasterxml.jackson.databind.JavaType.isReferenceType() Z" – KeizerHarm

+0

@KeizerHarm probablement vous avez oublié votre getter/setter ou le type que vous essayez de désérialiser est faux , par exemple, stockez "hi" dans un attribut entier – cralfaro

-1

Vous pouvez obtenir l'idée de ce code désérialiser,

public class testCustomDeSerializer extends JsonDeserializer<test> { 

public testCustomDeSerializer() { 
    this(null); 
} 

public TestCustomDeSerializer(Class t) { 
    // super(t); 
} 

@Override 
public Test deserialize(JsonParser p, DeserializationContext ctx) throws IOException, JsonProcessingException { 
    ObjectCodec objectCodec = p.getCodec(); 
    JsonNode node = objectCodec.readTree(p); 

    ObjectMapper objectMapper = new ObjectMapper(); 
    Test test= new Test(); 


    test.setId(node.get("line").asText()); 

    List<elements> elementList = new ArrayList<>(); 
    JsonNode elementsNode = node.get("elements"); 
    Iterator<JsonNode> slaidsIterator = elementsNode.elements(); 
    while (slaidsIterator.hasNext()) { 
     Steps steps= new Steps(); 
     JsonNode slaidNode = slaidsIterator.next(); 
     JsonNode stepNode= (JsonNode) slaidNode.get("Steps"); 
     BoundingPoly in = objectMapper.readValue(stepNode.toString(), Steps.class); 
     elementsNode.setSteps(in); 
     /// continue 

return 
     } 

Hope it helps

1

Je viens d'essayer votre code d'échantillon et curieusement, il fonctionne.

Pouvez-vous s'il vous plaît vérifier vos importations, si le JSON arrive comme prévu et si les getters, setters, constructors sont là?

+0

Avec le paquet com.fasterxml.jackson ne fonctionne pas – cralfaro

+0

Les constructeurs devraient être mis en œuvre avec le this.var = var et tout? Je pensais qu'ils étaient supposés être vides. – KeizerHarm

+0

soit vide et setters ou full constructors (set tous les champs) –