2013-04-30 3 views
2

나는 다음과 같은 클래스가 :JSON 객체로 트리를 직렬화

TreeNode.cs

public class TreeNode : IEnumerable<TreeNode> 
{ 
    public readonly Dictionary<string, TreeNode> _children = new Dictionary<string, TreeNode>(); 

    public readonly string Id; 
    public TreeNode Parent { get; private set; } 

    public TreeNode(string id) 
    { 
     this.Id = id; 
    } 

    public TreeNode GetChild(string id) 
    { 
     return this._childs[id]; 
    } 

    public void Add(TreeNode item) 
    { 
     if (item.Parent != null) 
     { 
      item.Parent._childs.Remove(item.Id); 
     } 

     item.Parent = this; 
     this._childs.Add(item.Id, item); 
    } 

    public IEnumerator<TreeNode> GetEnumerator() 
    { 
     return this._childs.Values.GetEnumerator(); 
    } 

    IEnumerator IEnumerable.GetEnumerator() 
    { 
     return this.GetEnumerator(); 
    } 

    public int Count 
    { 
     get { return this._childs.Count; } 
    } 
} 

FolderStructureNode.cs 그래서

public class FolderStructureNode : TreeNode 
{ 
    //Some properties such as FolderName, RelativePath etc. 
} 

을 나는 물체가있을 때 유형이 FolderStructureNode 인 경우 본질적으로 각 노드가 폴더를 나타내는 트리 데이터 구조입니다. 이 객체를 JsonObject로 직렬화하려고합니다. 나는 JavaScriptSerializer와 NewtonSoft를 모두 시도했다. 내가 올바른 JSON을 얻기 위해 직렬화 어떻게

Tree

: 직렬화시

[ 
    [ 
    [] 
    ], 
    [ 
    [] 
    ], 
    [] 
] 

, 나무가 다음과 같이 보입니다 - 두 경우 모두에서 나는 출력이 으려고 목적? 나는 나무를 가로 질러 스스로 json을 만들어야합니까?

+0

저는 serializer가 객체의 속성을 살펴보고 대신 _childs 사전을 속성으로 감싸는 것이 좋다고 생각합니다. – Christian

+1

문제는'TreeNode' 클래스가'IEnumerable '을 구현하여 시리얼 라이저가 노드를 배열로 직렬화 할 수 있다는 것입니다 (귀하의 경우 비어 있음). IEnumerable 구현 코드를 보지 않고 왜 비어 있는지 말할 수 없다. – fero

+0

전체 TreeNode 클래스를 추가했습니다. – mridula

답변

1

내 의견에 말했듯이 TreeNode 클래스는 IEnumerable<TreeNode>을 구현하므로 배열로 serialize됩니다. 따라서 TreeNode이 직렬화 될 때 볼 수있는 유일한 것은 노드의 하위 노드입니다. 이 아이들은 (물론) 마지막 잎 노드까지 어레이로 직렬화됩니다. 잎 노드에는 자식이 없으므로 빈 배열로 직렬화됩니다. 그래서 JSON 출력이 이렇게 보입니다.

당신은 정확하게 당신이 원하는 것을 JSON 출력 지정하지 않은,하지만 난 당신이 원하는 것은 이런 식으로 생각 :

{ 
    "Sales Order": { }, 
    "RFP": 
    { 
     "2169": { } 
    }, 
    "Purchase Order": 
    { 
     "2216": { } 
    } 
} 

이 달성하려면 TreeNode 클래스는 객체로 직렬화해야합니다.

class TreeNodeConverter : JsonConverter 
{ 
    public override bool CanConvert(Type objectType) 
    { 
     // we can serialize everything that is a TreeNode 
     return typeof(TreeNode).IsAssignableFrom(objectType); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     // we currently support only writing of JSON 
     throw new NotImplementedException(); 
    } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     // we serialize a node by just serializing the _children dictionary 
     var node = value as TreeNode; 
     serializer.Serialize(writer, node._children); 
    } 
} 

이 그럼 당신은 그래서 JsonConverterAttributeTreeNode 클래스를 장식해야합니다 : 내 생각에 (그리고 Newtonsoft Json.NET을 사용하는 당신을 제안/가정), 당신은 다음과 같이 나타납니다 사용자 정의 변환기 클래스를 작성해야 serializer는 TreeNode 개체를 serialize 할 때 변환기를 사용해야 함을 알고 있습니다. 당신이 Json.NET을 사용하지 않는 경우

[JsonConverter(typeof(TreeNodeConverter))] 
public class TreeNode : IEnumerable<TreeNode> 
{ 
    // ... 
} 

, 내가 정확히 무엇을 말할 수는 없지만 대신 IEnumerableIDictionary 때문에 시리얼 라이저는 키 - 상대하고 알을 구현한다면 그것은 도움이 될 수 있습니다 가치 쌍.

+0

IEnumerable을 제거한 이유는 실제로 필요하지 않았기 때문입니다. 이제는 작동했습니다 .. 많이 고마워요! 그러나 배열 내의 객체가 직렬화되지 않는 이유를 알지 못했습니다. – mridula

+0

그들은 직렬화를 얻었습니다.그러나 배열로 자식 노드를 포함하는 배열로 직렬화되며 배열로도 직렬화됩니다. 그래서 배열을 얻지 못할 것입니다. 마지막 자식 (리프 노드)은 자식을 포함하지 않으므로 빈 배열로 직렬화됩니다. ID는 배열과 같아야하기 때문에 ID와 같은 다른 어떤 것으로 직렬화 할 수 없습니다. – fero

관련 문제