잭슨 - 범용 클래스를 사용하여 역직렬화
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);
}
먼저 시리얼라이즈를 하고 나서 시리얼라이즈를 해제할 수 있습니다.
그래서 시리얼라이즈를 할 때는@JsonTypeInfo
Jackson이 당신의 json 데이터에 클래스 정보를 쓸 수 있도록 합니다.할 수 있는 일은 다음과 같습니다.
Class Data <T> {
int found;
@JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="@class")
Class<T> hits
}
그런 다음 역직렬화 시 Jackson이 실제로 변수가 히트하는 클래스로 데이터를 역직렬화했음을 확인할 수 있습니다.
Jackson 2.5부터는 TypeFactory.construct Parametersric Type(Class parametrized, Class...)을 사용하여 문제를 해결할 수 있습니다. parameterClasses) 메서드를 사용하여 잭슨을 스트레이트하게 정의할 수 있습니다.JavaType
매개 변수화된 클래스 및 해당 매개 변수화된 유형을 지정하면 됩니다.
에의 역직렬화를 실시하는 경우Data<String>
, 다음을 수행할 수 있습니다.
// the json variable may be a String, an InputStream and so for...
JavaType type = mapper.getTypeFactory().constructParametricType(Data.class, String.class);
Data<String> data = mapper.readValue(json, type);
클래스가 복수의 파라미터화 타입을 선언했을 경우, 이 작업은 그다지 어렵지 않습니다.
class Data <T, U> {
int found;
Class<T> hits;
List<U> list;
}
다음과 같은 작업을 할 수 있습니다.
JavaType type = mapper.getTypeFactory().constructParametricType(Data.class, String.class, Integer);
Data<String, Integer> data = mapper.readValue(json, type);
클래스 데이터의 경우 <>
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);
여기서 무엇인가는 콘크리트 타입입니다.검증된 유형별로 래퍼가 필요합니다.그렇지 않으면 Jackson은 어떤 개체를 만들어야 하는지 알 수 없습니다.
역직렬화해야 하는 JSON 문자열은 파라미터에 대한 유형 정보를 포함해야 합니다.T
.
매개 변수로 전달될 수 있는 모든 클래스에 잭슨 주석을 추가해야 합니다.T
수업하다Data
따라서 파라미터 유형에 대한 유형 정보가T
Jackson이 JSON 문자열에서 읽거나 쓸 수 있습니다.
라고 가정해 봅시다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 {
}
파라미터로 할 수 각 그 슈퍼타입가 1회 T
붙어 에 대한 를 포함합니다.잭슨은 파라미터에 대한 정보를 포함할 것입니다.T
JSON에 있습니다. 「JSON」을 수 .T
컴파일 시.
이 Jackson 문서 링크는 Polymorphic Diserialization에 대해 설명하지만 이 질문에도 도움이 됩니다.
public class Data<T> extends JsonDeserializer implements ContextualDeserializer {
private Class<T> cls;
public JsonDeserializer createContextual(DeserializationContext ctx, BeanProperty prop) throws JsonMappingException {
cls = (Class<T>) ctx.getContextualType().getRawClass();
return this;
}
...
}
scala를 사용하여 컴파일 시 범용 유형을 알고 있지만 모든 API에서 TypeReference를 수동으로 전달하고 싶지 않다면 다음 코드를 사용할 수 있습니다(잭슨 2.9.5).
def read[T](entityStream: InputStream)(implicit typeTag: WeakTypeTag[T]): T = {
//nathang: all of this *crazy* scala reflection allows us to handle List[Seq[Map[Int,Value]]]] without passing
// new TypeReference[List[Seq[Map[Int,Value]]]]](){} to the function
def recursiveFindGenericClasses(t: Type): JavaType = {
val current = typeTag.mirror.runtimeClass(t)
if (t.typeArgs.isEmpty) {
val noSubtypes = Seq.empty[Class[_]]
factory.constructParametricType(current, noSubtypes:_*)
}
else {
val genericSubtypes: Seq[JavaType] = t.typeArgs.map(recursiveFindGenericClasses)
factory.constructParametricType(current, genericSubtypes:_*)
}
}
val javaType = recursiveFindGenericClasses(typeTag.tpe)
json.readValue[T](entityStream, javaType)
}
다음과 같이 사용할 수 있습니다.
read[List[Map[Int, SomethingToSerialize]]](inputStream)
언급URL : https://stackoverflow.com/questions/11664894/jackson-deserialize-using-generic-class
'programing' 카테고리의 다른 글
계수를 이용한 C 덧셈 (0) | 2022.08.14 |
---|---|
동적 외부 데이터를 반응적으로 처리하도록 VueJ/VueX 애플리케이션을 구성하는 방법 (0) | 2022.08.14 |
snprintf 및 Visual Studio 2010 (0) | 2022.08.14 |
Java에서 public, protected, package-private 및 private의 차이점은 무엇입니까? (0) | 2022.08.14 |
vuex 파일을 분할하려면 어떻게 해야 합니까? (0) | 2022.08.14 |