Java 解析动态包装的JSON数组

Java 解析动态包装的JSON数组,java,json,jackson,Java,Json,Jackson,我有一个抽象类,有许多具体的实现: public abstract Ticket { private Long id; private Currency fine; ... } public class SpeedingTicket extends Ticket { public Currency getFine(){ // Expensive! ... } } public class ParkingTicket extends Ti

我有一个抽象类,有许多具体的实现:

public abstract Ticket {
   private Long id;
   private Currency fine;
   ...
}

public class SpeedingTicket extends Ticket {
   public Currency getFine(){
      // Expensive!
      ...
   }
}

public class ParkingTicket  extends Ticket {
   public Currency getFine(){
      // Eh, not so bad
      ...
   }
}
当具体类序列化为JSON时,将使用简单名称speedingTickets或parkingTickets包装:

"_embedded": {
   "speedingTickets" :
    [{
      "id":1,
      "fine": "$190",
       ...,
    },
    {
      "id":2,
      "fine": "$100",
       ...,
    }]
}

由于我不知道在运行时我收到的是哪一个票证实现,如果数组用具体实现的简单名称包装,我如何使用JSON响应API解析JSON

我有一个技巧,我获取JSON的字符串值,并对其执行字符串操作substring、indexOf等,以仅返回大括号[…]之间的内容。我知道有更好的方法。。。

经过一些研究,我想我明天会尝试以下方法,看看是否有效:

JsonNode rootNode = mapper.readTree(jsonResponse);
String classImpl = Iterables.get(rootNode.get("_embedded").fields(), 0).textValue()

然后我可以说List tickets=response.readAsListjsonResponse,_embedded,classImpl,它应该允许我将JSON解析为一个列表,JSON对象是一组无序的键/值对。JSON数组是值的有序集合。值本身可以是对象或数组

在java中,使用org.json库解析json很容易

如何解析json数组的简短示例:

String str = "{ \"number\": [3, 4, 5, 6] }";
JSONObject obj = new JSONObject(str);
JSONArray arr = obj.getJSONArray("number");
for (int i = 0; i < arr.length(); i++)
    System.out.println(arr.getInt(i));

如果您使用的是标签所建议的Jackson,那么您需要使用-这正是知道如何反序列化到正确的子类型的问题

例如:

 @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="@class")
 class  { } 
这实际上是在JSON中包含类名,因此反序列化程序有足够的信息来正确选择要实例化的子类。大概是这样的:

"_embedded": {
   "parkingTickets" :[{
      "_type": "ParkingTicket.class",
      "id":100,
      "fine": "$15",
       ...,
    }]
}

您可以通过检查响应包含的变量来检查类型

JSONObject jsonObj = new JSONObject(response);
if(jsonObj.has("speedingTickets")){
    // parse speedingTickets
}else if(jsonObj.has("parkingTickets")){
    // parse parkingtickets
}

我想你没有抓住我问题的重点。如果你知道数字是关键的话,你上面所说的就行了。在我的情况下,键是动态的,由实现类的简单名称决定是的,我正在这样做。我使用@JsonTypeInfo和现有属性值来确定实现。然而,我的问题与我正在进行的功能单元测试有关。我通过API进行模拟调用,但是我无法将响应返回到对象中,因为键“parkingTickets”或“speedingTickets”根据其实现进行更改。如果您在问题中给出更全面的摘要,这将有所帮助。我想你指的是基于API实现的关键更改?如果同时控制API和客户机,则应将模型放在共享库中,以便两端的序列化/反序列化完全相同。如果你不控制API,你能做的最好的事情就是把它编码到文档中。我指的是基于具体类名的关键更改。因此,json中的键speedingTickets是由SpeedingTicket实现创建的。帕克提克也是这样。_embedded之后的值根据实现类名称why not do:tickets:[{…},{…},{…}进行更改然后将所有类型放在一个列表中?否则,创建一个ParkingTickets复数类并序列化它。关键是包装对象的内容有助于框架选择具体的实现类。不幸的是,我无法更改该值我考虑过这样做,但是有20多个实现类型。我不认为这是正确的大规模的实用性我的问题可能是关于解析一个json aray,它有一个动态生成的键。你的链接是关于属性的。
JSONObject jsonObj = new JSONObject(response);
if(jsonObj.has("speedingTickets")){
    // parse speedingTickets
}else if(jsonObj.has("parkingTickets")){
    // parse parkingtickets
}