Jackson 직렬화 해제, json의 루트 요소 무시
json의 부모 태그를 무시하는 방법
여기 내 아들이 있다.
String str = "{\"parent\": {\"a\":{\"id\": 10, \"name\":\"Foo\"}}}";
그리고 여기 json에서 매핑되는 클래스가 있습니다.
public class RootWrapper {
private List<Foo> foos;
public List<Foo> getFoos() {
return foos;
}
@JsonProperty("a")
public void setFoos(List<Foo> foos) {
this.foos = foos;
}
}
테스트 공개 클래스 Jackson Test {}입니다.
@Test
public void wrapRootValue() throws Exception {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationConfig.Feature.UNWRAP_ROOT_VALUE, true);
mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
String str = "{\"parent\": {\"a\":{\"id\": 10, \"name\":\"Foo\"}}}";
RootWrapper root = mapper.readValue(str, RootWrapper.class);
Assert.assertNotNull(root);
}
다음과 같은 에러가 표시됩니다.
org.codehaus.jackson.map.JsonMappingException: Root name 'parent' does not match expected ('RootWrapper') for type [simple type, class MavenProjectGroup.mavenProjectArtifact.RootWrapper]
Jackson의 주석이 제시한 솔루션을 찾았습니다.
(a) Annotate you class as below
@JsonRootName(value = "parent")
public class RootWrapper {
(b) It will only work if and only if ObjectMapper is asked to wrap.
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationConfig.Feature.UNWRAP_ROOT_VALUE, true);
작업 완료!!
잭슨의 탈직렬화 방식의 또 다른 문제:
'DeserializationConfig'인 경우.특징.UNWRAP_ROOT_VALUE configured'는 모든 json의 래핑을 해제하고 @JsonRootName(값 = "rootTagInJson")으로 주석이 지정되지 않은 클래스에서 이벤트를 발생시키지 않습니다.
클래스에 @JsonRootName 주석이 붙어 있는 경우에만 루트 태그를 언랩합니다.그렇지 않으면 언랩하지 마십시오.
root 태그 언랩의 사용 예를 다음에 나타냅니다.
###########################################################
Unwrap only if the class is annotated with @JsonRootName.
############################################################
잭슨 소스 코드의 ObjectMapper를 약간 변경하여 jar의 새 버전을 만들었습니다. 1. 이 메서드를 ObjectMapper에 배치합니다.
// Ash:: Wrap json if the class being deserialized, are annotated
// with @JsonRootName else do not wrap.
private boolean hasJsonRootName(JavaType valueType) {
if (valueType.getRawClass() == null)
return false;
Annotation rootAnnotation = valueType.getRawClass().getAnnotation(JsonRootName.class);
return rootAnnotation != null;
}
2. Edit ObjectMapper method ::
Replace
cfg.isEnabled(DeserializationConfig.Feature.UNWRAP_ROOT_VALUE)
with
hasJsonRootName(valueType)
3. Build your jar file and use it.
https://github.com/FasterXML/jackson-databind의 TestRootName.java에서 가져온 예를 통해 보다 나은 방법을 찾을 수 있습니다.특히 RootName("")과 함께 사용하는 경우:
private ObjectMapper rootMapper()
{
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.WRAP_ROOT_VALUE, true);
mapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
return mapper;
}
public void testRootUsingExplicitConfig() throws Exception
{
ObjectMapper mapper = new ObjectMapper();
ObjectWriter writer = mapper.writer().withRootName("wrapper");
String json = writer.writeValueAsString(new Bean());
assertEquals("{\"wrapper\":{\"a\":3}}", json);
ObjectReader reader = mapper.reader(Bean.class).withRootName("wrapper");
Bean bean = reader.readValue(json);
assertNotNull(bean);
// also: verify that we can override SerializationFeature as well:
ObjectMapper wrapping = rootMapper();
json = wrapping.writer().withRootName("something").writeValueAsString(new Bean());
assertEquals("{\"something\":{\"a\":3}}", json);
json = wrapping.writer().withRootName("").writeValueAsString(new Bean());
assertEquals("{\"a\":3}", json);
bean = wrapping.reader(Bean.class).withRootName("").readValue(json);
assertNotNull(bean);
}
봄에 편안한 어플리케이션을 개발하다가 비슷한 문제를 겪었습니다.저는 매우 이기종 API를 지원해야 했습니다.그 중 일부는 루트 요소를 포함했고 다른 하나는 지원하지 않았습니다.이 속성을 실시간으로 구성하는 것보다 더 좋은 솔루션을 찾을 수 없었습니다.잭슨에서 클래스별 루트 요소가 풀리는 것을 지원하지 않는 것은 매우 유감입니다.어쨌든, 누군가는 이게 도움이 될 거야.
@Component
public class ObjectMapper extends com.fasterxml.jackson.databind.ObjectMapper {
private void autoconfigureFeatures(JavaType javaType) {
Annotation rootAnnotation = javaType.getRawClass().getAnnotation(JsonRootName.class);
this.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, rootAnnotation != null);
}
@Override
protected Object _readMapAndClose(JsonParser jsonParser, JavaType javaType) throws IOException, JsonParseException, JsonMappingException {
autoconfigureFeatures(javaType);
return super._readMapAndClose(jsonParser, javaType);
}
}
매우 간단합니다.
개체 매퍼의 인스턴스를 생성하고 루트 값 줄 바꿈 및 줄 바꿈을 사용하도록 설정합니다.
ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.WRAP_ROOT_VALUE);
mapper.enable(DeserializationFeature.UNWRAP_ROOT_VALUE);
더하다
@JsonRootName("yourname")
DTO에 대한 주석
@JsonRootName("root")
public class YourDto {
// ...
}
Seagabond의 POST 업데이트로서 파라미터 값을 쓸 때 동일한 효과를 얻으려면 추가 쓰기 방법을 덮어쓸 수 있습니다.
@Component
public class ObjectMapper extends com.fasterxml.jackson.databind.ObjectMapper {
private void autoconfigureFeatures(Object value) {
JavaType javaType = _typeFactory.constructType(value.getClass());
autoconfigureFeatures(javaType);
}
private void autoconfigureFeatures(JavaType javaType) {
Annotation rootAnnotation = javaType.getRawClass().getAnnotation(JsonRootName.class);
this.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, rootAnnotation != null);
}
@Override
public void writeValue(DataOutput out, Object value) throws IOException {
autoconfigureFeatures(value);
super.writeValue(out, value);
}
@Override
public void writeValue(Writer w, Object value) throws IOException, JsonGenerationException, JsonMappingException {
autoconfigureFeatures(value);
super.writeValue(w, value);
}
@Override
public byte[] writeValueAsBytes(Object value) throws JsonProcessingException {
autoconfigureFeatures(value);
return super.writeValueAsBytes(value);
}
@Override
public String writeValueAsString(Object value) throws JsonProcessingException {
autoconfigureFeatures(value);
return super.writeValueAsString(value);
}
@Override
protected Object _readMapAndClose(JsonParser jsonParser, JavaType javaType) throws IOException, JsonParseException, JsonMappingException {
autoconfigureFeatures(javaType);
return super._readMapAndClose(jsonParser, javaType);
}
}
저도 이런 문제에 직면해 있었습니다.RestTemplate 및 그 MessageConverters 설정을 정의한 컨피규레이션클래스에 코드 행을 추가했습니다.
Annotation rootAnnotation = mapper.getTypeFactory().getClass().getAnnotation(JsonRootName.class); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); mapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, Objects.nonNull(rootAnnotation));
기본적으로 이 구성은 제공된 클래스가 '@JsonRootName'으로 주석을 달고 있는지 여부를 Mapper가 식별하는 데 도움이 되며, 그렇지 않으면 루트를 검색할 필요가 없습니다.그것이 당신과 다른 사람들에게 도움이 되기를 바랍니다.
언급URL : https://stackoverflow.com/questions/8837018/jackson-json-deserialization-ignore-root-element-from-json
'programing' 카테고리의 다른 글
AngularJS에서 csv 파일 내용을 읽는 방법은 무엇입니까? (0) | 2023.03.19 |
---|---|
angularjs에서 선택 상자의 기본값을 설정하려면 어떻게 해야 합니까? (0) | 2023.03.19 |
반응 - 최소 예외가 발생했습니다. (0) | 2023.03.19 |
Ajax를 통해 Django에서 어레이를 게시하는 방법 (0) | 2023.03.14 |
NewtonSoft를 사용하여 JSON 개체의 속성을 업데이트하는 방법 (0) | 2023.03.14 |