简体   繁体   English

将复杂的JSON反序列化为Java,类嵌套多个级别

[英]Deserialize complex JSON to Java, classes nested multiple levels deep

I am trying to make the Json output from Cucumber into a single Java object. 我试图将Cucumber的Json输出转换为单个Java对象。 This contains objects nested four levels deep, and I am having trouble deserializing it. 这包含嵌套四层深度的对象,我无法反序列化它。 I am presently using Jackson, but open to suggestions. 我现在正在使用杰克逊,但愿意接受建议。 Here is my Json code: 这是我的Json代码:

{
"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"
}

I have tried a number of different approaches. 我尝试了很多不同的方法。 First I used nested inner classes, but it appeared you had to make them static, which I feared would not work since I have multiple instances of the same object within one (multiple "element"-objects in the root, for example). 首先我使用了嵌套的内部类,但是看起来你必须让它们成为静态的,我担心这样做是不行的,因为我在同一个对象中有多个实例(例如,根中有多个“元素” - 对象)。 Then I tried putting them in separate classes, with Json annotations. 然后我尝试将它们放在单独的类中,使用Json注释。 Here's where that got me (omitting setters): 这就是我的地方(省略了setters):

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(){}
}

For clarification, here 'sa class diagram of how the nesting works. 为了澄清, 这里是一个嵌套如何工作的类图。

This solution gives me the following error: 此解决方案给出了以下错误:

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

Here is the code doing the actual mapping: 这是执行实际映射的代码:

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

Is there a quick fix to this approach to make it work, or should I try something entirely different? 有没有快速解决这种方法使其工作,或者我应该尝试完全不同的东西?

Ok I spent some time debugging and trying to figure out what was the problem, and finally was something pretty obvious. 好吧,我花了一些时间调试并试图找出问题所在,最后是非常明显的事情。

implements Serializable

Thats the line I added to MatchObject and worked. 这是我添加到MatchObject并且工作的线。

When we try to deserialize some object first we have to make those classes implements the interface Serializable 当我们首先尝试反序列化某个对象时,我们必须使这些类实现Serializable接口

I just tried your sample code and oddly, it works. 我只是尝试了你的示例代码,奇怪的是,它的工作原理。

Can you please double check your imports, if the JSON is coming in as provided and the getters, setters, constructors are actually there? 如果JSON按照提供的方式进入并且getter,setter,构造函数实际存在,你能否请仔细检查你的导入?

You can get the idea from this code to deserialize, 您可以从此代码中获取反序列化的想法,

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 希望能帮助到你

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM