2016-10-17 5 views
1

트리 구조의 데이터를 자바 객체로 나타내려고하고 JSON 객체로 변환하려고합니다. 유래 항목의 도움으로해시 맵을 JSON 객체로 변환하는 동안 Gson에서 stackoverflowerror 받기

는 :

ArrayList<Pair> list= new ArrayList<>(); 
list.add(new Pair("6", "4")); 
list.add(new Pair("5", "4")); 
list.add(new Pair("4", "3")); 
list.add(new Pair("2", "3")); 
list.add(new Pair("3", "null")); 

Map<String, Node> o_map= new HashMap<>(); 
for (Pair l: list) { 
Node parent = o_map.getOrDefault(l.getParentId(), new Node(l.getParentId())); 
Node child = o_map.getOrDefault(l.getChildId(), new Node(l.getChildId())); 
parent.children.add(child); 
child.parent = parent; 
o_map.put(parent.id, parent); 
o_map.put(child.id, child); 
} 
Gson gs = new Gson(); 
System.out.println(gs.toJson(o_map)); 
} 

그러나 아동과 부모 :

Convert java arrayList of Parent/child relation into tree?

hashmap to JSON using GSON 내가 주요 기능 및 "쌍"목록 아래에 있었다

는 쌍을 포함 이 코드는 다음을 반환합니다.

Exception in thread "main" java.lang.StackOverflowError 
    at java.io.StringWriter.write(StringWriter.java:112) 
    at com.google.gson.stream.JsonWriter.string(JsonWriter.java:576) 
    at com.google.gson.stream.JsonWriter.writeDeferredName(JsonWriter.java:402) 
    at com.google.gson.stream.JsonWriter.beginArray(JsonWriter.java:287) 
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:95) 
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:61) 
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68) 
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:112) 
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:239) 
    at com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:968) 

오류.

왜 그런 오류가 반환되는지 알 수 없습니다. 그 이유는 무엇일까요? 미리 감사드립니다.

+0

해시 맵 >을 json 개체로 변환해야합니다. – nenana

+0

이렇게 쓰면 안됩니다.'ArrayList list = new ArrayList (); ' – Mark

+0

json에 트리 구조가 있어야합니다. 그렇게하기 위해 hashmap을 json으로 변환해야합니다. 나는 json에게 한 쌍의리스트를 쓰는 다른 대안을 시도했지만 결과는 내가 찾던 것이 아니었다. – nenana

답변

1

당신은 당신의 Node 클래스 정의를 포함하지 않았다, 그러나 나는 이런 식으로 뭔가 보이는 것 같은데요 :

public class Node { 
    public final String id; 
    public Node parent; 
    public final ArrayList<Node> children = new ArrayList<>(); 

    public Node(String id) { 
    this.id = id; 
    } 
} 

이 메모리에 트리 데이터 구조 을 표현하는 좋은 방법입니다 (일부 무시를 공용 필드 사용과 같은 관련없는 스타일 문제). 그러나 직렬화는 불가능합니다. 왜? Node이 null이 아닌 parent을 가지고 있기 때문에주기적인 관계가 있습니다. 즉, 하위 항목에 하위 항목에 대한 참조가 포함되어 있으며 하위 항목에 하위 항목에 대한 참조가 포함되어 있습니다. 있습니다 .. user guide에서

: 그 무한 재귀의 원인이되므로 당신은 순환 참조와 객체를 직렬화 할 수

참고.

우리는이 간단한 예와 같은 오류 트리거 할 수

Node root = new Node("A"); 
Node child = new Node("B"); 
root.children.add(child); 
child.parent = root; 
System.out.println(new Gson().toJson(root)); // passing in child would similarly fail 

그래서 우리는이 문제를 어떻게 해결할 수 있습니까? 그것은 당신이 원하는 행동에 달려 있습니다. 쉬운 옵션 중 하나는 Gson이 parent 필드를 직렬화하지 못하게하는 것입니다 (우리는 children 목록에서 다시 만들 수 있으므로 필요하지 않습니다). 이렇게하려면 mark parent as transient과 Gson은 결과에 포함시키지 않습니다. 부모 관계를 명시 적으로 기록하는 것이 더 도움이된다면 마찬가지로 childrentransient 필드로 만들 수 있습니다. 그러나 children 필드를 직렬화하면 루트 노드를 전달할 수 있고 전체 트리가 가로지를 수 있다는 장점이 있습니다.

또 다른 옵션은 Map<String, Node>이 아닌 다른 데이터 구조를 직렬화하는 것입니다. 현재 각 노드 ID는 Node 객체 (여기에는 모든 다른 노드에 대한 참조가 포함되어 있음)에 매핑됩니다. 즉, 주기적 관계가 있다면 아직도 이상한 JSON을 얻게 될 것입니다. Map<String, String> 또는 Map<String, List<String>> 데이터 구조가 될 수있는 ID-> 부모 또는 ID-> 자식 관계를 직렬화하는 것이 실제로 원하는 것과 같은처럼 보입니다. Gson은 직렬화에 문제가 없습니다.그것이 원하는 구조라면, 단순히 트리를 가로 질러 그러한 데이터 구조를 만들거나 Node을 원하는 JSON 구조로 변환하는 custom deserializer을 정의 할 수 있습니다.

관련 문제