클래스 이름을 JSON Jackson 일련화의 루트 키로 사용
내게 포조가 있다고 가정해봐.
import org.codehaus.jackson.map.*;
public class MyPojo {
int id;
public int getId()
{ return this.id; }
public void setId(int id)
{ this.id = id; }
public static void main(String[] args) throws Exception {
MyPojo mp = new MyPojo();
mp.setId(4);
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationConfig.Feature.WRAP_ROOT_VALUE, true);
System.out.println(mapper.getSerializationConfig().isEnabled(SerializationConfig.Feature.WRAP_ROOT_VALUE));
System.out.println(mapper.writeValueAsString(mp));
}
}
Jackson Object Mapper를 사용하여 연재하면
true
{"id":4}
하지만 나는 원한다
true
{"MyPojo":{"id":4}}
제가 샅샅이 찾아봤는데, 잭슨의 문서는 정말 체계적이지 않고 대부분 구식이에요.
@JsonTypeInfo
네 반에 변함이 없어
package com.test.jackson;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
@JsonTypeInfo(include=As.WRAPPER_OBJECT, use=Id.NAME)
public class MyPojo {
// Remain same as you have
}
출력:
{
"MyPojo": {
"id": 4
}
}
Jackson을 사용하지 않지만 검색 결과 WRAP_ROOT_VALUE라는 설정이 검색되었습니다.
단일 속성 JSON 개체 내에서 루트 값(일반적으로 JSON 개체이지만 모든 유형일 수 있음)을 만들 수 있도록 설정할 수 있는 기능입니다. 여기서 키는 주석 인스펙터(uses@XmlRootElement.name를 지원하는 JAXB의 경우) 또는 폴백(비수식 클래스 이름)에 의해 결정됩니다.이 기능은 대부분 JAXB 호환성을 목적으로 하고 있습니다.
디폴트 설정은 false 입니다.즉, 루트 값은 랩되지 않습니다.
다음과 같이 매퍼를 설정할 수 있습니다.
objectMapper.configure(SerializationConfig.Feature.WRAP_ROOT_VALUE, true);
도움이 됐으면 좋겠는데...
이를 실현하는 방법은 다음과 같습니다.
Map<String, MyPojo> singletonMap = Collections.singletonMap("mypojo", mp);
System.out.println(mapper.writeValueAsString(singletonMap));
출력 { "mypojo" : { "id" : 4}
여기서 장점은 json 객체의 루트 키의 이름을 지정할 수 있다는 것입니다.위의 코드에 따르면 mypojo가 루트 키가 됩니다.이 접근법은 hursead.js와 같은 자바 스크립트템플릿을 json 오브젝트의 반복에 사용할 때 가장 유용합니다.
위해서는, 「 」를 가 있습니다.JsonTypeInfo
클래스, 특히 WAPPER_OBJECT에 대한 주석
@JsonTypeName("foo")
@JsonTypeInfo(include = JsonTypeInfo.As.WRAPPER_OBJECT ,use = JsonTypeInfo.Id.NAME)
public class Bar(){
)
여기에는 다음과 같은 주석도 있습니다.
@JsonRootName(value = "my_pojo")
public class MyPojo{
...
}
다음 항목이 생성됩니다.
{
"my_pojo" : {...}
}
다음과 같은 래퍼 클래스를 사용하여 가장 간단한 해결 방법을 생각해 보십시오.
class Wrapper {
public MyPojo MyPojo;
}
코드로 포장/포장할 수 있습니까?
이 밖에도, 이러한 추가 json 오브젝트 엔트리를 원하는 이유를 알면 도움이 됩니다.xml api를 통해 json을 에뮬레이트하는 libs(xml과 json 사이의 임피던스, xml에서 json으로 변환하기 때문에)에 의해 실행되는 것으로 알고 있지만 순수 json 솔루션에서는 일반적으로 필요하지 않습니다.
실제 타입이 무엇인지 알 수 있도록 하기 위해서입니까?만약 그렇다면 잭슨이 자동으로 처리하도록 하기 위해 다형 타입 정보를 활성화하는 것을 고려해 주시겠습니까?(자세한 것에 대하여는, 1.5 릴리스 노트, PTH의 엔트리를 참조해 주세요).
다른 방법이 있는데 그게 나한테 효과가 있었어서드파티제의 항아리를 사용하고 있기 때문에 주석을 제어할 수 없습니다.그래서 나는 약간의 해킹을 통해 글을 써야 했다.
정의::org.codehaus.jackson.map.ser.BeanSerializerFactory.findBeanProperties(SerializationConfig, BasicBeanDescription)
다음과 같이 자산을 추가합니다.
List<BeanPropertyWriter> props = super.findBeanProperties(config, beanDesc);
BeanPropertyWriter bpw = null;
try {
Class cc = beanDesc.getType().getRawClass();
Method m = cc.getMethod("getClass", null);
bpw = new BeanPropertyWriter("$className", null, null, m, null,true, null);
} catch (SecurityException e) {
// TODO
} catch (NoSuchMethodException e) {
// TODO
}
props.add(bpw);
return props;
이렇게 하면 제어력이 향상되고 다른 종류의 필터도 할 수 있습니다.
@JsonTypeInfo(include=As.WRAPPER_OBJECT, use=Id.NAME)
이 주석은 Arun Prakash가 제안한 것처럼 완벽하게 작동합니다.Json을 다음 형태로 가져오려고 했습니다.
{"Rowset":{"ROW":{"receiptno":"881604199388936","status":"SUCCESS"}}}
이렇게 되는 거야
{"ROW":{"receiptno":"881604199388936","status":"SUCCESS"}}
이제 그 주석이 내 문제를 해결했다.
이에 대한 OP의 솔루션을 듣고 싶습니다.RESTful 웹 서비스에서 클라이언트의 XML 또는 JSON으로 개체를 직렬화하는 것과 같은 문제가 있습니다.Javascript 클라이언트는 에서 해석할 수 있도록 래핑 유형을 알아야 합니다.유형을 URI 패턴에 결합하는 것은 옵션이 아닙니다.
감사해요.
편집: Spring MappingJacksonJsonMarshaller가 마샬링 시 래핑클래스를 추가한다는 것을 알고 있었기 때문에 디버깅에서 코드를 확인했더니 키가 래핑명이고 값이 오브젝트가 되는 단일 키와 값의 쌍이 있는 해시맵으로 Spring이 전달되는 것을 알 수 있었습니다.그래서 JacksonJsonProvider를 확장하여 writeTo() 메서드를 덮어쓰고 다음을 추가했습니다.
HashMap<String, Object> map = new HashMap<String, Object>();
map.put(value.getClass().getSimpleName(), value);
super.writeTo(map, type, genericType, annotations, mediaType, httpHeaders,entityStream);
조금 엉터리지만 잘 작동한다.
RootName과 함께 사용합니다.
objectMapper.writer().withRootName(MyPojo.class.getName());
모든 JSON은 백엔드 타입(문자열)과 프론트 엔드에 렌더링에 사용하는 컴포넌트 타입(angular 또는 Vue를 사용하는 경우)을 모두 포함하는 것이 좋습니다.
이렇게 하는 이유는 단일 코드 세트로 다양한 유형을 처리할 수 있기 때문입니다.
예를 들어 vue에서는 데이터에 UI 구성 요소의 이름을 포함하면 상위 템플릿에서 단일 태그만 사용하여 다른 유형의 자식 목록을 렌더링하는 화면을 만들 수 있습니다.
<component :is="child.componentType"/>.
백엔드 시스템과 웹 서비스의 경우 - 수신 페이로드에 따라 적절한 프로세서 클래스를 검색하여 모든 웹 서비스에 로깅, 감사 및 예외 처리를 제공하는 단일 웹 서비스 프로세서 클래스를 사용하는 것이 좋습니다.이것에 의해, 모든 Web 서비스의 실장이 완전하게 같게 되어(약 3 행의 코드), 콜의 라이프 사이클에 걸쳐 상세한 이벤트 로그가 취득됩니다.서비스 코드별로 기록되지 않습니다.
JSON을 감싸고 있는 타입을 가지는 것으로써, JSON은 자기 문서화되어 있습니다.표시되는 것이 속성뿐이라면 대응하는 엔드 포인트를 찾을 때까지 무엇을 보고 있는지 알 수 없습니다.
데이터 기반 소프트웨어를 작성하려면 처리 중인 항목을 식별할 수 있어야 합니다.
언급URL : https://stackoverflow.com/questions/2435527/use-class-name-as-root-key-for-json-jackson-serialization
'source' 카테고리의 다른 글
스타일링 리액트 네이티브 피커 (0) | 2023.03.22 |
---|---|
json 파일을 mongo로 Import하는 올바른 방법 (0) | 2023.03.22 |
WebKit, FireBug 또는 IE8 Developer Tool과 같은 디버거에서 JavaScript를 동적으로 로드하는 것을 디버깅할 수 있습니까? (0) | 2023.03.22 |
create-react-app을 TypeScript와 함께 사용할 수 있습니다. (0) | 2023.03.22 |
Angularjs 필터가 null이 아닙니다. (0) | 2023.03.22 |