使用 Java Jackson 反序列化 json 并基于根元素调用与该根元素中的 Json 对象匹配的不同类

问题描述

我是反序列化的新手,我正在尝试为我的班级反序列化复杂的 JSON。我正在使用 Jackson 2.12.1。我想知道当有多种情况映射到不同的根元素时,如何将以下 JSON 结构映射到我的类

我的类路径的资源文件夹中有一个 JSON 文件,它是这样的:

   {
      "Employee":{
         "firstName":"First Name","lastName":"Last Name","department":"Department"
      },"Student":{
         "firstName":"Student First Name","lastName":"Student Last Name","studentID":"1234"
      }
   }

我分别为 EmployeeCar 设置了 2 个类,它们分别扩展了 Person 抽象类及其类似内容

@Getter
@Setter
public abstract class person{
    private String firstName;
    private String lastName;
}

@Getter
@Setter
@JsonRootName(value = "Employee")
public Employee extends person{
    private String department;
}

@Getter
@Setter
@JsonRootName(value = "Student")
public Student extends person{
    private String studentID;
}

public class MainClass{

     public static void main(String []args){
        String jsonFile = FileUtils.readFiletoString(new File("src/main/resources/myFile.json"),"UTF-8");
        final ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE,true);
        Employee eventInfo = objectMapper.readValue(jsonFile,Employee.class);

        //This works for Employee but I want to make sure that it works for Student as well based on the ROOT ELEMENT value within the JSON
     }
} 

这适用于 Employee,但如何根据 JSON 中的不同 ROOT ELEMENT 值将其配置为适用于所有类型?我觉得我缺少一些基本的东西,有人可以帮我吗?

PS:我正在使用 Lombok 项目中的 @Getter 和 @Setter

解决方法

我试图查看杰克逊的许多示例和文档。我终于能够让它工作了。这只是一个示例,可以用作映射类的基础。就我而言,我试图根据我映射到不同类的元素来查看存在的元素类型。因此,这可能不会完全按照您的预期工作,但仍然可以作为参考。

我在这里发布相同的内容,以便将来对某人有所帮助:

如果以下是 JSON 文件内容:

[
  {
    "isA": "Type1","name": "Test","foo": "val1","foo": "val2","bar": "val3","foo": {
      "myField": "Value1","myField": "value2"
    }
  },{
    "isA": "Type2","name": "Test1","myField": "value2"
    }
  }
]


public void xmlConverter(InputStream jsonStream) throws IOException {
    // Get the JSON Factory and parser Object
    final JsonParser jsonParser = new JsonFactory().createParser(jsonStream);
    final ObjectMapper objectMapper = new ObjectMapper();
    jsonParser.setCodec(objectMapper);
    
    // Check the first element is ARRAY if not then invalid JSON throw error
    if (jsonParser.nextToken() != JsonToken.START_ARRAY) {
      throw new IllegalStateException("Expected content to be an array");
    }
    
    jsonParser.nextToken();
    
    // Loop until the end of the events file
    while (jsonParser.nextToken() != JsonToken.END_ARRAY) {

      // Get the node
      final JsonNode jsonNode = jsonParser.readValueAsTree();

      //Check if the JsonNode is valid if not then exit the process
      if (jsonNode == null || jsonNode.isNull()) {
        System.out.println("End Of File");
        break;
      }

      // Get the eventType
      final String eventType = jsonNode.get("isA").asText();

      // Based on eventType call different type of class
      switch (eventType) {
        case "Type1":
          final Type1 type1Info = objectMapper.treeToValue(jsonNode,Type1.class);
          break;
        case "Type2":
          final Type2 type2Info = objectMapper.treeToValue(jsonNode,Type2.class);
          break;
        default:
          System.out.println("JSON event does not match any of event : " + eventType);
          break;
      }
    }
}