我需要映射一个 JSON 字符串,其中包含名为 long 和 short 的 values:
"status": {
"long": "Finished",
"short": "F",
"elapsed": 90
}
我尝试了以下课程:
public class Status {
@JsonProperty("long")
public String _long;
@JsonProperty("short")
public String _short;
@JsonProperty("elapsed")
public Object elapsed;
}
使用命令:
objectMapper.readValue(resBody, Response.class);
响应包含状态部分:
{
"response": {
"id": 157016,
"timezone": "UTC",
"date": "2019-08-10T11:30:00+00:00",
"timestamp": 1565436600,
"status": {
"long": "Long Value",
"short": "LV",
"elapsed": 20
}
}
}
但我仍然收到以下错误:
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException:无法识别的字段“long”
如何解决这个问题?我无法控制 JSON 格式。
回答1
好吧,这显然不是解决问题的完美方法,但人们可能会发现它是一种有用的解决方法:
由于我不关心这些 values,我将重命名它们的名称并相应地调整类成员名称:
在 json 字符串 resBody 我得到的响应中,我将执行以下操作
@NotNull
private static String mitigateLongAndShortValueNames(String resBody) {
resBody = resBody.replaceAll("\"long\":", "\"longValue\":");
resBody = resBody.replaceAll("\"short\":", "\"shortValue\":");
return resBody;
}
和改变
public class Status {
@JsonProperty("long")
public String _long;
@JsonProperty("short")
public String _short;
@JsonProperty("elapsed")
public Object elapsed;
}
至
public class Status {
public String longValue;
public String shortValue;
public Object elapsed;
}
它对我有用!
回答2
解决问题的方法之一是选择您感兴趣的 json 部分,结合将您的 json 转换为 JsonNode
对象的 https://fasterxml.github.io/jackson-databind/javadoc/2.12/com/fasterxml/jackson/databind/ObjectMapper.html#readTree-java.lang.String- 方法,然后选择 JsonNode
的部分您正在使用与 /response/status
路径表达式匹配的 https://fasterxml.github.io/jackson-databind/javadoc/2.12/com/fasterxml/jackson/databind/JsonNode.html#at-java.lang.String- 方法查找的对象,如下所示:
//it contains only the status labelled node of your json
JsonNode statusNode = mapper.readTree(json).at("/response/status");
在您可以使用 https://fasterxml.github.io/jackson-databind/javadoc/2.12/com/fasterxml/jackson/databind/ObjectMapper.html#treeToValue-com.fasterxml.jackson.core.TreeNode-java.lang.Class- 方法将 JsonNode
转换为您的 Status
类获得预期结果之后:
JsonNode statusNode = mapper.readTree(json).at("/response/status");
Status status = mapper.treeToValue(statusNode, Status.class);
//ok, it prints {"long":"Long Value","short":"LV","elapsed":20}
System.out.println(mapper.writeValueAsString(status));
回答3
完整的异常消息应如下所示:com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "long" (class ...), not marked as ignorable (n known properties: ...)
如果您对某些属性不感兴趣,那么在解析过程中使用 ignore
会更容易、更清晰。在数据类上使用注释或在 objectmapper 上使用 DeserializationFeature。
回答4
扩展评论: Status
和 "status":...
部分没有问题, @JsonProperty()
用于处理重命名。您可能将错误的类传递给 readValue()
。
public class TestClass {
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
TestClass test= mapper.readValue(
"{\r\n" +
" \"response\": {\r\n" +
" \"id\": 157016,\r\n" +
" \"status\": {\r\n" +
" \"long\": \"Long Value\",\r\n" +
" \"short\": \"LV\",\r\n" +
" \"elapsed\": 20\r\n" +
" }\r\n" +
" }\r\n" +
"}",TestClass.class); // <-- here, it's not Response, but an outer class
System.out.println(test.response.id);
System.out.println(test.response.status._long);
}
public Response response; // <-- containing "response"
static public class Response {
public long id;
public Status status;
}
static public class Status {
@JsonProperty("long")
public String _long;
@JsonProperty("short")
public String _short;
@JsonProperty("elapsed")
public Object elapsed;
}
}
显示器
157016 Long Value
正如预期的那样。为简洁起见,仅从外部对象中保留 id
。