2016-09-25 3 views
0

좋은 하루 내 동료 개발자 호출되지 않습니다. 하지만 행운을 들이지 않고 Json 문자열에 객체 목록을 직렬화하려고합니다. 내 상속 계층 구조는 다음과 같습니다.안드로이드 GSON AbstractAdapter.serialize은 (다형성 직렬화)

interface IFloorPlanPrimitive 
abstract class FloorPlanPrimitiveBase implements IFloorPlanPrimitive 
class Wall extends FloorPlanPrimitiveBase 
class Mark extends FloorPlanPrimitiveBase 

아주 간단합니다. 각 반에는 몇 가지 필드가 있습니다. 필자는 웹에서 문제를 검색하고이 어댑터 클래스를 추가하여 직렬화/직렬화를 용이하게했습니다. 현재 직렬화 할 수 없으므로 여기에 집중하겠습니다.

public class FloorPlanPrimitiveAdapter implements 
     JsonSerializer<FloorPlanPrimitiveBase>, JsonDeserializer<FloorPlanPrimitiveBase> { 

    @Override 
    public JsonElement serialize(FloorPlanPrimitiveBase src, Type typeOfSrc, JsonSerializationContext context) { 
     JsonObject result = new JsonObject(); 
     result.add("type", new JsonPrimitive(src.getClass().getSimpleName())); 
     result.add("properties", context.serialize(src, src.getClass())); 

     return result; 
    } 

    @Override 
    public FloorPlanPrimitiveBase deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { 
     JsonObject jsonObject = json.getAsJsonObject(); 
     String type = jsonObject.get("type").getAsString(); 
     JsonElement element = jsonObject.get("properties"); 

     try { 
      final String packageName = IFloorPlanPrimitive.class.getPackage().getName(); 
      return context.deserialize(element, Class.forName(packageName + '.' + type)); 
     } catch (ClassNotFoundException cnfe) { 
      throw new JsonParseException("Unknown element type: " + type, cnfe); 
     } 
    } 
} 

그리고 이것은 내가 사용하는 방법이다 : 나는 직렬화 할 때 FloorPlanPrimitiveAdapterserialize 메서드가 호출되지 않는 것을 볼 수있는 간단한 디버그에서

public String getFloorPlanAsJSon() { 
    GsonBuilder gsonBilder = new GsonBuilder(); 
    gsonBilder.registerTypeAdapter(FloorPlanPrimitiveBase.class, new FloorPlanPrimitiveAdapter()); 
    Gson gson = gsonBilder.create(); 

    List<IFloorPlanPrimitive> floorPlan = mRenderer.getFloorPlan(); 
    String jsonString = gson.toJson(floorPlan); 

    return jsonString; 
} 

을 따라서 나는 그 "유형"을하지 않습니다 및 "속성"필드에 있습니다. 대신 나는 곧은 Json 문자열을 얻는다. 이것은 유형의 불일치 때문인 것 같습니다. IFloorPlanPrimitive을 직렬화하도록 요청하고 있지만이 인터페이스를 구현하는 FloorPlanPrimitiveBase을 전달합니다. 내 기대는 그것이 작동해야했다 :)

이 상황에서 직렬화 및 비 직렬화를 어떻게 다룰 수 있는지에 대해 누구도 지적 할 수 있습니까? 그 "불일치"를 극복하는 방법?

미리 감사드립니다.

친절한 분께 Greg.

답변

0

좋은 하루,

내 문제를 내 문제와 공유하고 싶습니다. 나는 이것이 다른 사람들에게 도움이되기를 바랍니다. 또한,이 솔루션에 결함이 있는지 알고 싶습니다.

그래서 처음에는 사용법. 나는 SO에 대한 또 다른 해답을 보았다. 또한 GSON GitHub의에 this 문제는 (특히 내가 toJson() 방법으로 형식 매개 변수를 전달하는이 도움이 배웠습니다 :

public String getFloorPlanAsJSon() { 
    GsonBuilder builder = new GsonBuilder(); 

    final Type type = (new TypeToken<List<FloorPlanPrimitiveBase>>() {}).getType(); 
    builder.registerTypeAdapter(type, new FloorPlanAdapter()); 
    Gson gson = builder.create(); 

    List<IFloorPlanPrimitive> floorPlan = mRenderer.getFloorPlan(); 
    String jsonString = gson.toJson(floorPlan, type); 

    return jsonString; 
} 

그리고 지금은 실제로 SO (답변 그것에서 버그가 조심 this에서 걸린 Adapter - .

public class FloorPlanAdapter implements JsonSerializer<List<FloorPlanPrimitiveBase>> { 

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

    @Override 
    public JsonElement serialize(List<FloorPlanPrimitiveBase> src, Type typeOfSrc, 
           JsonSerializationContext context) { 
     JsonArray array = new JsonArray(); 

     for (FloorPlanPrimitiveBase primitiveBase : src) { 
      JsonObject primitiveJson = new JsonObject(); 

      String className = primitiveBase.getClass().getCanonicalName(); 
      primitiveJson.addProperty(CLASSNAME, className); 

      JsonElement elem = context.serialize(primitiveBase); 
      primitiveJson.add(INSTANCE, elem); 

      array.add(primitiveJson); 
     } 
     return array; 
    } 
} 

당신이 List<>에있는 모든 개체를 통해 루프 내 원래의 질문에 바로 FloorPlanPrimitiveBaseAdapter처럼 처리 볼 수 있듯이

: JSON에 넣어 클래스의 이름 대신 요소의 클래스의 ArrayList를)입니다

이렇게 직렬화하는 방법입니다.

@Override 
public List<FloorPlanPrimitiveBase> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { 
    final String packageName = IFloorPlanPrimitive.class.getPackage().getName(); 
    List<FloorPlanPrimitiveBase> result = new ArrayList<>(); 
    JsonArray jsonArray = json.getAsJsonArray(); 

    for (JsonElement element : jsonArray) { 
     final JsonObject asJsonObject = element.getAsJsonObject(); 
     String className = asJsonObject.get(CLASSNAME).getAsString(); 
     JsonElement serializedInstance = asJsonObject.get(INSTANCE); 

     Class<?> klass; 
     try { 
      klass = Class.forName(packageName + '.' + className); 
      final FloorPlanPrimitiveBase deserializedInstance = context.deserialize(serializedInstance, klass); 
      result.add(deserializedInstance); 
     } catch (ClassNotFoundException e) { 
      e.printStackTrace(); 
     } 
    } 
    return result; 
}