잭슨 동적 속성 이름
필드 유형에 따라 필드 중 하나의 이름이 다르게 지정되도록 개체를 직렬화하고 싶습니다.예를 들어 다음과 같습니다.
public class Response {
private Status status;
private String error;
private Object data;
[ getters, setters ]
}
여기, 나는 그 필드를 원한다.data
연재되다data.getClass.getName()
항상 라는 분야를 가지고 있는 대신data
상황에 따라 다른 타입이 포함되어 있습니다.
잭슨을 이용해서 어떻게 그런 묘기를 부릴 수 있을까요?
이 솔루션을 사용하여 보다 심플한 솔루션을 사용하였습니다.@JsonAnyGetter
주석은 마법처럼 작동했어요
import java.util.Collections;
import java.util.Map;
public class Response {
private Status status;
private String error;
@JsonIgnore
private Object data;
[getters, setters]
@JsonAnyGetter
public Map<String, Object> any() {
//add the custom name here
//use full HashMap if you need more than one property
return Collections.singletonMap(data.getClass().getName(), data);
}
}
래퍼도 커스텀시리얼라이저도 필요 없습니다.
커스텀 사용.
public class Response {
private String status;
private String error;
@JsonProperty("p")
@JsonSerialize(using = CustomSerializer.class)
private Object data;
// ...
}
public class CustomSerializer extends JsonSerializer<Object> {
public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
jgen.writeStartObject();
jgen.writeObjectField(value.getClass().getName(), value);
jgen.writeEndObject();
}
}
그런 다음 다음 다음 두 개체를 직렬화한다고 가정합니다.
public static void main(String... args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
Response r1 = new Response("Error", "Some error", 20);
System.out.println(mapper.writeValueAsString(r1));
Response r2 = new Response("Error", "Some error", "some string");
System.out.println(mapper.writeValueAsString(r2));
}
첫 번째 인쇄물은 다음과 같습니다.
{"status":"Error","error":"Some error","p":{"java.lang.Integer":20}}
그리고 두 번째는:
{"status":"Error","error":"Some error","p":{"java.lang.String":"some string"}}
나는 그 이름을 사용했다.p
그것은 단지 하나의 역할로서 기능할 것이기 때문에 포장된 오브젝트에 대해서p
레이스 홀더삭제할 경우 전체 클래스에 대해 커스텀시리얼라이저를 작성해야 합니다(예:JsonSerializer<Response>
.
나만의 해결책.
@Data
@EqualsAndHashCode
@ToString
@JsonSerialize(using = ElementsListBean.CustomSerializer.class)
public class ElementsListBean<T> {
public ElementsListBean()
{
}
public ElementsListBean(final String fieldName, final List<T> elements)
{
this.fieldName = fieldName;
this.elements = elements;
}
private String fieldName;
private List<T> elements;
public int length()
{
return (this.elements != null) ? this.elements.size() : 0;
}
private static class CustomSerializer extends JsonSerializer<Object> {
public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) throws IOException,
JsonProcessingException
{
if (value instanceof ElementsListBean) {
final ElementsListBean<?> o = (ElementsListBean<?>) value;
jgen.writeStartObject();
jgen.writeArrayFieldStart(o.getFieldName());
for (Object e : o.getElements()) {
jgen.writeObject(e);
}
jgen.writeEndArray();
jgen.writeNumberField("length", o.length());
jgen.writeEndObject();
}
}
}
}
주석을 사용할 수 있습니다.JsonTypeInfo
잭슨에게 정확하게 알려주고 커스텀 시리얼라이저를 쓸 필요가 없습니다.이 정보를 포함할 수 있는 방법은 다양합니다만, 구체적인 질문에는As.WRAPPER_OBJECT
그리고.Id.CLASS
. 예:
public static class Response {
private Status status;
private String error;
@JsonTypeInfo(include = As.WRAPPER_OBJECT, use = Id.CLASS)
private Object data;
}
그러나 String이나 Integer와 같은 원시 유형에서는 작동하지 않습니다.이 정보는 원래 JSON으로 표시되며 Jackson은 이 정보를 처리하는 방법을 알고 있기 때문에 원본을 위해 필요하지 않습니다.주석을 사용하면 필요할 때 무료로 역직렬화를 사용할 수 있습니다.다음은 예를 제시하겠습니다.
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
Response r1 = new Response("Status", "An error", "some data");
Response r2 = new Response("Status", "An error", 10);
Response r3 = new Response("Status", "An error", new MyClass("data"));
System.out.println(mapper.writeValueAsString(r1));
System.out.println(mapper.writeValueAsString(r2));
System.out.println(mapper.writeValueAsString(r3));
}
@JsonAutoDetect(fieldVisibility=Visibility.ANY)
public static class MyClass{
private String data;
public MyClass(String data) {
this.data = data;
}
}
그 결과:
{"status":"Status","error":"An error","data":"some data"}
{"status":"Status","error":"An error","data":10}
{"status":"Status","error":"An error","data":{"some.package.MyClass":{"data":"data"}}}
@tlogbon 응답을 바탕으로 특정/동적인 파일명으로 아이템 목록을 정리하는 솔루션을 소개합니다.
public class ListResource<T> {
@JsonIgnore
private List<T> items;
@JsonIgnore
private String fieldName;
public ListResource(String fieldName, List<T> items) {
this.items = items;
this.fieldName = fieldName;
}
@JsonAnyGetter
public Map<String, List<T>> getMap() {
return Collections.singletonMap(fieldName, items);
}
언급URL : https://stackoverflow.com/questions/12134231/jackson-dynamic-property-names
'source' 카테고리의 다른 글
리액트 앱의 setInterval (0) | 2023.02.13 |
---|---|
$.ajax가 포함된 쿼리 문자열 대신 JSON을 전송하려면 어떻게 해야 합니까? (0) | 2023.02.13 |
React에서 상위 컴포넌트 인스턴스에 액세스할 수 있는 방법이 있습니까? (0) | 2023.02.13 |
이름/값 구조를 위한 JSON 스키마 작성 방법 (0) | 2023.02.13 |
ngCordova를 사용한 애니메이션 방향 화살표 "주변" 스타일 (0) | 2023.02.13 |