我期待能够使用Jackson将几种JSON格式解析为相同的以下对象:
public class SpeechAction extends Action {
public String[] speechText;
}
知道我的父类是:
public class Action {
public String onCompletedEvent;
}
我希望能够支持的格式(为了便于编写,因为它将由人而不是机器编写一段时间):
1。简单字符串:
{
"speech": <speech_text>
}
2。字符串数组:
{
"speech":[
<variant1>,
<variant2>,
…
]
}
第3。嵌套的简单字符串:
{
"speech": {
"speechText": <speech_text>,
"onCompletedEvent":<EVENT_NAME>
}
}
4。嵌套字符串数组:
{
"speech": {
"speechText":[
<variant1>,
<variant2>,
…
],
"onCompletedEvent":<EVENT_NAME>
}
}
使用以下代码成功解析格式1,3和4:
public class SpeechAction extends Action {
@JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
@JsonProperty("speechText")
public String[] speechText;
public SpeechAction() {
speechText = new String[]{""};
}
public SpeechAction(String... text) {
speechText = text;
}
public SpeechAction(String text) {
speechText = new String[]{text};
}
}
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT)
@JsonSubTypes({@JsonSubTypes.Type(value = SpeechAction.class, name = "speech")})
public class Action {
@JsonProperty("onCompletedEvent")
public String 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立即丢失了。
我探索了自定义反序列化方法,但另外不想失去注释的优势,我没有看到如何以一种不会为我父母的课程重复的方式做到这一点&#34; onCompletedEvent&# 34;属性(因为我有很多从Action继承的类)。
感谢您的领导!
答案 0 :(得分:0)
Jackson API为您提供了一个名为JsonNode的通用对象,它可以解析任何类型的JSON流,除非您收到有效的JSON输入。因此,您始终可以考虑将JSON模式4视为通用JSON,因为它涵盖了所有方案。
我坚信存在设计缺陷。鉴于这种情况,我想以三种方式处理这个问题陈述。
ObjectMapper
映射它们。JsonNode
将输入JSON映射到ObjectMapper
并找到所有必需字段。 (这是处理JSON的最天真的方式。)因为,您已经在评论中提到了我想向您展示的方法。
注意:我不想亲自采用这种方法。如果我是你,我将重新考虑我的设计并采用第一种或第二种方法。
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();
}
}
}
}
}