구성

2017-01-23 5 views
1

을 개체를 저장하고 관리하는 방법 나는이 수업이 있습니다구성

class A implements Composite 
{ 
    Composite b = new B(); 
} 

class B implements Composite 
{ 
} 

interface Composite 
{ 
} 

기본적으로 AB로 구성되어 나는 파일이 구성을 유지를 저장할. 활동에

나는이 작업을 수행 :

FileInputStream fileInputStream = null; 
try 
{ 
    fileInputStream = openFileInput(filename); 
} 
catch(FileNotFoundException e) 
{} 

InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream)l; 
BufferReader bufferedReader = new BufferedReader(inputStreamReader); 
StringBuilder stringBuilder = new StringBuilder(); 

String line; 

try 
{ 
    while((line = bufferedReader.readLine()) != null) 
    { 
     stringBuilder.append(line); 
    } 
} 
catch(IOException e) 
{ 
} 

String json = stringBuilder.toString(); 
Gson gson2 = new Gson(); 

// Exception here. 
A a2 = gson2.fromJson(json, A.class); 

문제는 클래스의 내부 객체 B 함께 A. GSON이 보이지 않는다 :

String filename = "myfile.txt"; 

A a = new A(); 

Gson gson = new Gson(); 
String s = son.toJson(a); 

FileOutputStream outputStream; 
try 
{ 
    outputStream = openFileOutput(filename, Context.MODE_PRIVATE); 
    outputStream.write(s.getBytes); 
    outputStream.close(); 
} 
catch(Exception e) 
{ 
} 

그럼 내가 읽은이 코드를 사용 그 종류는 B입니다. 그래서 나는이 예외를 얻을 :

JNI는 응용 프로그램에서 오류를 발견 : A,하지 클래스 내

+0

내 대답을 업데이트하고 테스트 했으므로 전체 코드 [here] (https://gist.github.com/lelloman/a009a8b7c863071551c6dbc2d0fdaa0d) – lelloman

답변

1

문제는 해당 인터페이스를 구현하는 클래스를 직렬화 할 필요가 있도록 인터페이스가 어떤 속성이 없다는 것입니다. 당신은이와 함께 그것은 또한 클래스 이름을 저장하는 복합 인스턴스를 직렬화 할 때

public static class CompositeAdapter implements JsonSerializer<Composite>, JsonDeserializer<Composite> { 

    private static final String CLASSNAME = "CLASSNAME"; 
    private static final String DATA = "DATA"; 

    public Composite deserialize(JsonElement jsonElement, Type type, 
         JsonDeserializationContext jsonDeserializationContext) throws JsonParseException { 

     JsonObject jsonObject = jsonElement.getAsJsonObject(); 
     JsonPrimitive prim = (JsonPrimitive) jsonObject.get(CLASSNAME); 
     String className = prim.getAsString(); 
     Class klass = null; 
     try { 
      klass = Class.forName(className); 
     } catch (ClassNotFoundException e) { 
      e.printStackTrace(); 
      // TODO: handle somehow 
     } 
     return jsonDeserializationContext.deserialize(jsonObject.get(DATA), klass); 
    } 

    public JsonElement serialize(Composite jsonElement, Type type, JsonSerializationContext jsonSerializationContext) { 
     JsonObject jsonObject = new JsonObject(); 
     jsonObject.addProperty(CLASSNAME, jsonElement.getClass().getName()); 
     jsonObject.add(DATA, jsonSerializationContext.serialize(jsonElement)); 
     return jsonObject; 
    } 
} 

기본적 복합 인스턴스를 직렬화 코드를 빌더

GsonBuilder builder = new GsonBuilder(); 
builder.registerTypeAdapter(Composite.class, new CompositeAdapter()); 
Gson gson = builder.create(); 

으로 GSON 인스턴스를 생성하고 정의해야 특성을 역 직렬화 할 때 실제 클래스의 인스턴스를 생성합니다 (예를 들어 B). 이 방법을 사용하면 Composite를 구현하는 각 클래스에 대해 serializer 및 deserializer를 만들지 않아도되지만 클래스 이름 (패키지 이름을 포함한 전체 이름)을 변경하면이를 deserialize 할 수 없습니다.

2

원인은 GSON가 보는 것을해야한다 복합 형 및 인터페이스의 객체를 만들 수 없습니다. 내가 잘못 본 게 아니라면, Gson은 런타임 정보 (즉, 클래스 B의 객체를 포함하는 변수)가 아니라 컴파일 시간 정보 (즉, 변수의 데이터 유형)를 사용합니다. 당신이 다음에 당신에게 클래스를 변경하는 경우

, 잘 직렬화해야합니다

class A implements Composite 
{ 
    B b = new B(); 
} 

class B implements Composite 
{ 
} 

interface Composite 
{ 
} 
+0

을 찾을 수 있습니다. 작동해야하지만 콘크리트가 아닌 인터페이스에 코딩하고 싶습니다. 수업. –

+0

이 경우 클래스 A에 대한 고유 한 직렬 변환기를 작성할 수 있습니다. https://github.com/google/gson/blob/master/UserGuide.md#TOC-Writing-a-Serializer – Ray