[java] Jackson-일반 클래스를 사용하여 직렬화 해제

json 문자열이 있는데 다음 클래스로 직렬화 해제해야합니다.

class Data <T> {
    int found;
    Class<T> hits
}

어떻게합니까? 이것은 일반적인 방법입니다

mapper.readValue(jsonString, Data.class);

그러나 T가 의미하는 것을 어떻게 언급합니까?



답변

사용하는 TypeReference각 제네릭 형식에 대한 개체 를 생성하고 역 직렬화에 사용해야합니다. 예를 들어-

mapper.readValue(jsonString, new TypeReference<Data<String>>() {});


답변

그렇게 할 수 없습니다 :과 같이 완전히 해결 된 유형을 지정해야합니다 Data<MyType>. T변수 일 뿐이며 의미가 없습니다.

그러나 그것이 T정적으로 알려진 것이 아니라는 것을 의미한다면 , TypeReference동적으로 동등한 것을 만들어야합니다 . 언급 된 다른 질문은 이미 이것을 언급 할 수 있지만 다음과 같이 보일 것입니다.

public Data<T> read(InputStream json, Class<T> contentClass) {
   JavaType type = mapper.getTypeFactory().constructParametricType(Data.class, contentClass);
   return mapper.readValue(json, type);
}


답변

먼저 직렬화를 수행 한 다음 직렬화 해제를 수행 할 수 있습니다.

따라서 직렬화를 수행 할 때 @JsonTypeInfoJackson이 클래스 정보를 json 데이터에 쓰도록 해야합니다 . 당신이 할 수있는 일은 다음과 같습니다

Class Data <T> {
    int found;
    @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="@class")
    Class<T> hits
}

그런 다음 deserialize하면 Jackson이 변수 적중이 실제로 런타임에 클래스로 데이터를 deserialize 한 것을 알 수 있습니다.


답변

클래스 Data <>

ObjectMapper mapper = new ObjectMapper();
JavaType type = mapper.getTypeFactory().constructParametrizedType(Data.class, Data.class, Parameter.class);
Data<Parameter> dataParam = mapper.readValue(jsonString,type)


답변

Util 클래스에서 정적 메소드를 작성하십시오. 파일에서 Json을 읽고 있습니다. 당신은 또한 readValue에 문자열을 줄 수 있습니다

public static <T> T convertJsonToPOJO(String filePath, Class<?> target) throws JsonParseException, JsonMappingException, IOException, ClassNotFoundException {
        ObjectMapper objectMapper = new ObjectMapper();
        return objectMapper.readValue(new File(filePath), objectMapper .getTypeFactory().constructCollectionType(List.class, Class.forName(target.getName())));
}

용법:

List<TaskBean> list =  Util.<List<TaskBean>>convertJsonToPOJO("E:/J2eeWorkspaces/az_workspace_svn/az-client-service/dir1/dir2/filename.json", TaskBean.class);


답변

일반 유형의 유형을 알고있는 다른 클래스로 랩핑 할 수 있습니다.

예 :

class Wrapper {
 private Data<Something> data;
}
mapper.readValue(jsonString, Wrapper.class);

여기에 구체적인 유형이 있습니다. 당신은 reified type마다 wrapper가 필요합니다. 그렇지 않으면 Jackson은 어떤 객체를 만들지 알지 못합니다.


답변

역 직렬화해야하는 JSON 문자열에는 parameter에 대한 유형 정보가 포함되어야합니다 T.
Jackson이 매개 변수 유형에 대한 유형 정보 를 JSON 문자열에서 읽거나 쓸 수 있도록 매개 변수 T로 클래스에 전달할 수있는 모든 클래스에 Jackson 주석을 넣어야 합니다.DataT

T추상 클래스를 확장하는 모든 클래스가 될 수 있다고 가정 해 봅시다 Result.

class Data <T extends Result> {
    int found;
    Class<T> hits
}

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT)
@JsonSubTypes({
        @JsonSubTypes.Type(value = ImageResult.class, name = "ImageResult"),
        @JsonSubTypes.Type(value = NewsResult.class, name = "NewsResult")})
public abstract class Result {

}

public class ImageResult extends Result {

}

public class NewsResult extends Result {

}

매개 변수로 전달 될 수있는 각 클래스 (또는 공통 수퍼 타입) T 에 주석을 달면 Jackson은 매개 변수 T에 대한 정보를 JSON에 포함합니다. 그런 다음 T컴파일 타임에 매개 변수 를 몰라도 이러한 JSON을 직렬화 해제 할 수 있습니다 .
Jackson 문서 링크 는 다형성 역 직렬화에 대해 설명하지만이 질문을 참조하는 데 유용합니다.