英文:
Use Jackson deserializer to read child JSON object
问题
I have a Spring Boot application with Jackson dependency, and a Service with this code:
Dto dto = new ObjectMapper().readValue(jsonString, Dto.class);
I have a JSON similar to this one:
{
"meta": {
...
},
"results": [
{
"id": {"raw": "1"},
"name": {"raw": "Hello World"}
"number": {"raw": 7.5}
}
]
}
And I have a Java class like this one:
public class Dto {
private AnotherDto meta;
private List<ResultDto> results;
// getters/setters
}
public class ResultDto {
@JsonProperty("id")
private Wrapper<String> id;
// More fields and getters/setters
}
Then, I have a generic Wrapper class like this one (idea from Baeldung: https://www.baeldung.com/jackson-deserialization ):
@JsonDeserialize(using = WrapperDeserializer.class)
public class Wrapper<T> {
T value;
// getters/setters
}
Lastly, I have the next deserializer:
public class WrapperDeserializer extends JsonDeserializer<Wrapper<?>> implements ContextualDeserializer {
private JavaType type;
@Override
public Wrapper<?> deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
Wrapper<?> wrapper = new Wrapper<>();
wrapper.setValue(deserializationContext.readValue(jsonParser, type));
return wrapper;
}
@Override
public JsonDeserializer<?> createContextual(DeserializationContext deserializationContext, BeanProperty beanProperty) throws JsonMappingException {
this.type = beanProperty.getType().containedType(0);
return this;
}
}
The main doubt is, how I can access to jsonParser object in order to get the child JSON information? In this case, I would like to access {"raw": "1"}, so I could get the child into "raw" key and get the proper value, so ID "1" would be saved in final Java object.
I wouldn't want to make deserializationContext.readValue(jsonParser, type) as in this example, because it would throw this error:
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize value of type `java.lang.String` from Object value (token `JsonToken.START_OBJECT`)
at [Source:
Because {"raw": "1"} is not a valid String. I would want to have only the "1" value.
英文:
I have a Spring Boot application with Jackson dependency, and a Service with this code:
Dto dto = new ObjectMapper().readValue(jsonString, Dto.class);
I have a JSON similar to this one:
{
"meta": {
...
},
"results": [
{
"id": {"raw": "1"},
"name": {"raw": "Hello World"}
"number": {"raw": 7.5}
}
]
}
And I have a Java class like this one:
public class Dto {
private AnotherDto meta;
private List<ResultDto> results;
// getters/setters
}
public class ResultDto {
@JsonProperty("id")
private Wrapper<String> id;
// More fields and getters/setters
}
Then, I have a generic Wrapper class like this one (idea from Baeldung: https://www.baeldung.com/jackson-deserialization ):
@JsonDeserialize(using = WrapperDeserializer.class)
public class Wrapper<T> {
T value;
// getters/setters
}
Lastly, I have the next deserializer:
public class WrapperDeserializer extends JsonDeserializer<Wrapper<?>> implements ContextualDeserializer {
private JavaType type;
@Override
public Wrapper<?> deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
Wrapper<?> wrapper = new Wrapper<>();
wrapper.setValue(deserializationContext.readValue(jsonParser, type));
return wrapper;
}
@Override
public JsonDeserializer<?> createContextual(DeserializationContext deserializationContext, BeanProperty beanProperty) throws JsonMappingException {
this.type = beanProperty.getType().containedType(0);
return this;
}
}
The main doubt is, how I can access to jsonParser object in order to get the child JSON information? In this case, I would like to access {"raw": "1"}, so I could get the child into raw key and get the proper value, so ID "1" would be saved in final Java object.
I wouldn't want to make deserializationContext.readValue(jsonParser, type) as in this example, because it would throw this error:
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize value of type `java.lang.String` from Object value (token `JsonToken.START_OBJECT`)
at [Source:
Because {"raw": "1"} is not a valid String. I would want to have only the "1" value.
答案1
得分: 1
你已经非常接近了。主要问题是你在字段名称 value 处使用了,实际应该是 raw。另外,WrapperDeserializer 不是必要的。
所有代码都按你的要求,除了以下部分:
Wrapper.java
public class Wrapper<T> {
T raw;
// getters, setters & toString()
}
main
public static void main(String[] args) throws JsonMappingException, JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
String json = "{
"results": [
{
"id": {"raw": "1"},
"name": {"raw": "Hello World"},
"number": {"raw": 7.5}
}
]
}";
Dto readValue = objectMapper.readValue(json, Dto.class);
System.out.println(readValue);
}
输出
Dto [results=[ResultDto [id=Wrapper [raw=1], name=Wrapper [raw=Hello World], number=Wrapper [raw=7.5]]]]
英文:
You are really close. The main issue is that you used the field name value where it should be raw. Also, the WrapperDeserializer is not required.
All the code is as you have it besides the following:
Wrapper.java
public class Wrapper<T> {
T raw;
// getters, setters & toString()
}
main
public static void main(String[] args) throws JsonMappingException, JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
String json = "{\r\n" +
" \"results\": [\r\n" +
" {\r\n" +
" \"id\": {\"raw\": \"1\"},\r\n" +
" \"name\": {\"raw\": \"Hello World\"},\r\n" +
" \"number\": {\"raw\": 7.5}\r\n" +
" }\r\n" +
" ]\r\n" +
"}";
Dto readValue = objectMapper.readValue(json, Dto.class);
System.out.println(readValue);
}
Output
Dto [results=[ResultDto [id=Wrapper [raw=1], name=Wrapper [raw=Hello World], number=Wrapper [raw=7]]]]
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论