Java Jackson:POJO由JSON对象、字符串数组或字符串定义

Java Jackson:POJO由JSON对象、字符串数组或字符串定义,java,json,jackson,Java,Json,Jackson,我希望能够使用Jackson将几种JSON格式解析为相同的以下对象: public类SpeechAction扩展了动作{ 公共字符串[]speechText; } 知道我的父类是: 公共集体诉讼{ 公共字符串onCompletedEvent; } 我希望能够支持的格式(为了便于编写,因为它将由人而不是机器编写一段时间)是: 1。简单字符串: { “讲话”: } 2。字符串数组: { “讲话”:[ , , … ] } 3。嵌套的简单字符串: { “讲话”:{ “演讲稿”:, “onCo

我希望能够使用Jackson将几种JSON格式解析为相同的以下对象:

public类SpeechAction扩展了动作{
公共字符串[]speechText;
}
知道我的父类是:

公共集体诉讼{
公共字符串onCompletedEvent;
}
我希望能够支持的格式(为了便于编写,因为它将由人而不是机器编写一段时间)是:

1。简单字符串

{
“讲话”:
}
2。字符串数组

{
“讲话”:[
, 
, 
…
]
}
3。嵌套的简单字符串

{
“讲话”:{
“演讲稿”:,
“onCompletedEvent”:
}
}
4。嵌套字符串数组

{
“讲话”:{
“演讲稿”:[
, 
, 
…
],
“onCompletedEvent”:
}
}
使用以下代码成功解析格式1、3和4:

public类SpeechAction扩展了动作{
@JsonFormat(with=JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
@JsonProperty(“speechText”)
公共字符串[]speechText;
公开演讲{
speechText=新字符串[]{”“};
}
公开演讲(字符串…文本){
speechText=文本;
}
公众演讲(字符串文本){
speechText=新字符串[]{text};
}
}
@JsonTypeInfo(use=JsonTypeInfo.Id.NAME,include=JsonTypeInfo.As.WRAPPER\u对象)
@JsonSubTypes({@JsonSubTypes.Type(value=SpeechAction.class,name=“speech”)})
公共集体诉讼{
@JsonProperty(“onCompletedEvent”)
公共字符串onCompletedEvent;
}
但我还没能解决格式2的问题。我在尝试分析时遇到以下异常:

com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `com.nerus.app.actions.SpeechAction` out of START_ARRAY token
at [Source: (String)"{
    "speech": [
        "Hello there!",
        "Hey you!"
    ]
}
"; line: 2, column: 11]
通过使用@JsonCreator注释,我能够支持格式1和格式2,但3和4立即丢失

我探索了自定义反序列化器方法,但为了不想失去注释的优势,我没有看到如何以一种不会对父类的“onCompletedEvent”属性重复的方式来完成它(因为我有大量从Action继承的类)


谢谢你的任何线索

Jackson API为您提供了一个名为JsonNode的通用对象,它可以解析任何类型的JSON流,除非您收到有效的JSON输入。因此,您可以总是将JSON模式4看作是常见的JSON,因为它涵盖了所有的场景。 我坚信这是一个设计缺陷。鉴于这种情况,我想从三个方面来处理这个问题

  • 将所有JSON与问题中提到的类型4 JSON一样具有公共模式
  • 为4个JSON模式创建POJO,并使用Jackson API的
    ObjectMapper
    映射它们
  • 使用
    ObjectMapper
    将输入JSON映射到
    JsonNode
    ,并找到所有必需的字段。(这是处理JSON最简单的方法。)
  • 因为,你在评论中提到了原因,我想向你展示3种方式

    注意:我个人不想采用这种方法。如果我是你,我会重新考虑我的设计,并采用第一种或第二种方法

    public class JsonTest {
    
        public static void main(String[] args) throws JsonProcessingException, IOException {
            String jsoninpt = "{\r\n" + 
                    "   \"speech\": \"speech text\"\r\n" + 
                    "}";
            String jsoninpt1 = "{\r\n" + 
                    "   \"speech\": [\r\n" + 
                    "       \"speech text1\",\r\n" + 
                    "       \"speech text2\"\r\n" + 
                    "   ]\r\n" + 
                    "}";
    
            String jsonInpt2 = "{\r\n" + 
                    "    \"speech\": {\r\n" + 
                    "        \"speechText\": <speech_text>,\r\n" + 
                    "        \"onCompletedEvent\":<EVENT_NAME>\r\n" + 
                    "    }\r\n" + 
                    "}";
            String jsonInput3 = "{\r\n" + 
                    "    \"speech\": {\r\n" + 
                    "        \"speechText\":[\r\n" + 
                    "            <variant1>, \r\n" + 
                    "            <variant2>, \r\n" + 
                    "            …\r\n" + 
                    "        ],\r\n" + 
                    "        \"onCompletedEvent\":<EVENT_NAME>\r\n" + 
                    "    }\r\n" + 
                    "}";
    
    
            jsonParser(jsoninpt);
    
        }
    
        public static void jsonParser(String jsoninput) throws IOException {
            ObjectMapper mapper = new ObjectMapper();
            JsonNode jsonInputNode = mapper.readTree(jsoninput);
    
            System.out.println(mapper.writeValueAsString(jsonInputNode));
    
            if(jsonInputNode.has("speech")) {
                JsonNode value = jsonInputNode.get("speech");
                if(value.isTextual()) {
                    String speechText = value.asText();
                    System.out.println(speechText);
                }else if(value.isArray() || value.isObject()) {
                    Iterator<Entry<String, JsonNode>> speechObjects = value.fields();
                    while(speechObjects.hasNext()) {
                        Entry<String,JsonNode> speechObject = speechObjects.next();
                        String key = speechObject.getKey();
                        JsonNode node = speechObject.getValue();                    
                    }
            }
    
        }
        }
    
    }
    
    公共类JsonTest{
    公共静态void main(字符串[]args)抛出JsonProcessingException、IOException{
    字符串jsoninpt=“{\r\n”+
    “\”语音\“:\”语音文本\“\r\n”+
    "}";
    字符串jsoninpt1=“{\r\n”+
    “\“speech\”:[\r\n”+
    “\”语音文本1\”,\r\n“+
    “\”语音文本2\“\r\n”+
    “]\r\n”+
    "}";
    字符串jsonInpt2=“{\r\n”+
    “\”语音\“:{\r\n”+
    “\”speechText\“:,\r\n“+
    “\”onCompletedEvent\”:\r\n“+
    “}\r\n”+
    "}";
    字符串jsonInput3=“{\r\n”+
    “\”语音\“:{\r\n”+
    “\“speechText\”:[\r\n”+
    “,\r\n”+
    “,\r\n”+
    “…\r\n”+
    “],\r\n”+
    “\”onCompletedEvent\”:\r\n“+
    “}\r\n”+
    "}";
    jsonParser(jsoninpt);
    }
    公共静态void jsonParser(字符串jsoninput)引发IOException{
    ObjectMapper mapper=新的ObjectMapper();
    JsonNode jsonInputNode=mapper.readTree(jsoninput);
    System.out.println(mapper.writeValueAsString(jsonInputNode));
    if(jsonInputNode.has(“speech”)){
    JsonNode value=jsonInputNode.get(“语音”);
    if(value.isTextual()){
    String speechText=value.asText();
    System.out.println(speechText);
    }else if(value.isArray()| | value.isObject()){
    迭代器speechObjects=value.fields();
    while(speechObjects.hasNext()){
    条目speechObject=speechObjects.next();
    String key=speechObject.getKey();
    JsonNode节点=speechObject.getValue();
    }
    }
    }
    }
    }
    
    为什么不对所有JSON输入类型使用通用JSON格式“4”?您好@Phani Kumar Yadavilli,谢谢您的评论!我之所以考虑支持几种格式(完整格式4中较短的格式),是因为在可预见的未来,这些JSON将由人手工编写,而不是自动生成。在那种情况下,打字越简单越好。