2012-07-25 2 views
11

질문을 잘못 게시했습니다. 여기에 정확하게 질문을 게시하고 있습니다 ...Jackson - 일반 클래스 변수 Deserialize

HTTP 응답으로 json 문자열을 얻고 있습니다. 나는 그것의 구조를 안다. 다음과 같이이다 :

public class Json<T> { 
    public Hits<T> hits; 
} 
public class Hits<T> { 
    public int found; 
    public int start; 
    public ArrayList<Hit<T>> hit; 
} 
public class Hit<T> { 
    public String id; 
    public Class<T> data; 
} 

"데이터"필드는 모든 클래스에 속할 수 있습니다. 런타임에만 알 수 있습니다. 나는 매개 변수로 그것을 얻을 것이다. 이것이 내가 비 직렬화하는 방법입니다.

는 java.lang.Class의에서 개인 java.lang.class.Class를()에 액세스 할 수 없습니다 -

public <T> void deSerialize(Class<T> clazz) { 
    ObjectMapper mapper = new ObjectMapper(); 
    mapper.readValue(jsonString, new TypeReference<Json<T>>() {}); 
} 

는하지만 오류를 얻고있다. 액세스를 설정하지 못했습니다. java.lang.Class 생성자에 액세스 할 수 없게 만듭니다.

+0

질문을 복제하는 이유 (http://stackoverflow.com/questions/11664894/jackson-deserialize-using-generic-class/11681540 참조)? – StaxMan

+0

http://stackoverflow.com/questions/17400850/is-jackson-really-unable-to-deserialize-json-into-a-generic-type – lisak

답변

1

클래스 객체를 JSON에 직렬화 및 비 직렬화할까요? 어쩌면 그것을 Hit에서 String으로 유지하고 Class.forName을 시작하는 추가 getter를 만들 수 있습니다.

이 ...

는 어떻게 잭슨에게 말할까요 변수

public class Hit { 
    public String id; 
    public String data; 
    public Class<?> getDataClass() throws Exception { 
     return Class.forName(data); 
    } 
} 
+0

질문을 완전히 수정했습니다. 답장 해 주시겠습니까? – gnjago

+1

오류 : "새로운 Class 객체를 생성하려고합니다.하지만 생성자가 private이기 때문에 new Class()를 실행할 수 없습니다." 더 이상 이치에 맞지 않습니다. 샘플 JSON 문자열을 입력하십시오. 솔루션을 제안하는 것이 훨씬 쉬울 것입니다. 꽤 클래스 클래스의 serialize/deserializing 속성이 잘못된 경로라고 확신합니다. –

0

역 직렬화 일반 클래스? 그슨이 더 잘 할거야?

The Gson user guide includes a section 내가 문서화 한 예제가 여전히 불완전 할 수도 있지만 귀하가 달성하고자하는 바를 정확히 알고 있어야합니다.

In a blog post, I covered in more detail the solution using Gson 1.7.1. 다음은 관련 코드 예제입니다.

Jackson (1.8.2)을 사용하는 유사한 (그러나 더 복잡한) 솔루션도 동일한 블로그 게시물에서 설명하고 설명합니다. (서로 다른 접근 방법과 예제는 수백 줄의 코드를 사용, 그래서 여기를 다시 게시들을 생략했습니다.)

public class GsonInstanceCreatorForParameterizedTypeDemo 
{ 
public static void main(String[] args) 
{ 
    Id<String> id1 = new Id<String>(String.class, 42); 

    Gson gson = new GsonBuilder().registerTypeAdapter(Id.class, 
    new IdInstanceCreator()).create(); 
    String json1 = gson.toJson(id1); 
    System.out.println(json1); 
    // actual output: {"classOfId":{},"value":42} 
    // This contradicts what the Gson docs say happens. 
    // With custom serialization, as described in a 
    // previous Gson user guide section, 
    // intended output may be 
    // {"value":42} 

    // input: {"value":42} 
    String json2 = "{\"value\":42}"; 

    Type idOfStringType=new TypeToken<Id<String>>(){}.getType(); 
    Id<String> id1Copy = gson.fromJson(json2, idOfStringType); 
    System.out.println(id1Copy); 
    // output: classOfId=class java.lang.String, value=42 

    Type idOfGsonType = new TypeToken<Id<Gson>>() {}.getType(); 
    Id<Gson> idOfGson = gson.fromJson(json2, idOfGsonType); 
    System.out.println(idOfGson); 
    // output: classOfId=class com.google.gson.Gson, value=42 
} 
} 

class Id<T> 
{ 
private final Class<T> classOfId; 
private final long value; 

public Id(Class<T> classOfId, long value) 
{ 
    this.classOfId = classOfId; 
    this.value = value; 
} 

@Override 
public String toString() 
{ 
    return "classOfId=" + classOfId + ", value=" + value; 
} 
} 

class IdInstanceCreator implements InstanceCreator<Id<?>> 
{ 
@SuppressWarnings({ "unchecked", "rawtypes" }) 
public Id<?> createInstance(Type type) 
{ 
    Type[] typeParameters = 
    ((ParameterizedType) type).getActualTypeArguments(); 
    Type idType = typeParameters[0]; 
    return new Id((Class<?>) idType, 0L); 
} 
} 
10

당신은 제네릭 형식이 동적으로 사용할 수있는 경우, 명시 적으로 JavaType를 구축해야합니다

// do NOT create new ObjectMapper per each request! 
final ObjectMapper mapper = new ObjectMapper(); 

public Json<T> void deSerialize(Class<T> clazz, InputStream json) { 
    return mapper.readValue(json, 
     mapper.getTypeFactory().constructParametricType(Json.class, clazz)); 
} 
+0

내 경험으로는 작동하지 않지만 버그 일 수 있습니다. https://github.com/FasterXML/jackson-databind/issues/254 – lisak

+0

참조 된 버그에 다른 문제점이 있습니다 - 표시된 일반 유형 해결 위의 코드는 작동하지만 다른 가능한 문제는 해결하지 못합니다. – StaxMan

+0

예, 사과드립니다. 여기에서 해결되었습니다. http://stackoverflow.com/questions/17400850/is-jackson-really-unable-to-deserialize-json-into-a-generic-type – lisak

2

샘플 일반적인 역 직렬화 인터페이스 :

public interface Deserializable<T> { 
    static final ObjectMapper mapper = new ObjectMapper(); 

    @SuppressWarnings("unchecked") 
    default T deserialize(String rawJson) throws IOException { 
     return mapper.readValue(rawJson, (Class<T>) this.getClass()); 
    } 
} 
0
paramet에 대한 형식 정보를 포함해야합니다 직렬화 할 필요가

JSON 문자열 er T.
매개 변수 유형 T으로 전달할 수있는 모든 클래스에 Jackson 주석을 클래스 Json에 넣어야하므로 매개 변수 유형 T에 대한 유형 정보를 Jackson이 JSON 문자열에서 읽고 쓸 수 있습니다.

T은 추상 클래스 Result을 확장하는 모든 클래스가 될 수 있다고 가정 해 보겠습니다. 매개 변수 T로 전달 될 수있는 클래스 (또는 공통의 슈퍼 타입)의 각 주석되면

public class Json<T extends Result> { 
    public Hits<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 { 

} 

, 잭슨은 JSON에서 매개 변수 T에 대한 정보가 포함됩니다.그런 다음 컴파일시 매개 변수 T을 모른 채 이러한 JSON을 직렬 처리 해제 할 수 있습니다.
Jackson documentation link은 Polymorphic Deserialization에 대해 이야기하지만이 질문에 대해서도 참조하는 것이 유용합니다.

관련 문제