1

I have Node Class

public Node<T> Parent { get; private set; }
public T Value { get; set; }
private readonly List<Node<T>> _children = new List<Node<T>>();

public Node(T value)
{
    Value = value;
}

public Node<T> this[int index]
{
    get
    {
        return _children[index];
    }
}

public Node<T> Add(T value, int index = -1)
{
    var childNode = new Node<T>(value);
    Add(childNode, index);
    return childNode;
}

public void Add(Node<T> childNode, int index = -1)
{
    if (index < -1)
    {
        throw new ArgumentException("The index can not be lower then -1");
    }
    if (index > Children.Count() - 1)
    {
        throw new ArgumentException("The index ({0}) can not be higher then index of the last iten. Use the AddChild() method without an index to add at the end".FormatInvariant(index));
    }
    if (!childNode.IsRoot)
    {
        throw new ArgumentException("The child node with value [{0}] can not be added because it is not a root node.".FormatInvariant(childNode.Value));
    }

    if (Root == childNode)
    {
        throw new ArgumentException("The child node with value [{0}] is the rootnode of the parent.".FormatInvariant(childNode.Value));
    }

    if (childNode.SelfAndDescendants.Any(n => this == n))
    {
        throw new ArgumentException("The childnode with value [{0}] can not be added to itself or its descendants.".FormatInvariant(childNode.Value));
    }
    childNode.Parent = this;
    if (index == -1)
    {
        _children.Add(childNode);
    }
    else
    {
        _children.Insert(index, childNode);
    }
}

public Node<T> AddFirstChild(T value)
    {
        var childNode = new Node<T>(value);
        AddFirstChild(childNode);
        return childNode;
    }

    public void AddFirstChild(Node<T> childNode)
    {
        Add(childNode, 0);
    }

    public Node<T> AddFirstSibling(T value)
    {
        var childNode = new Node<T>(value);
        AddFirstSibling(childNode);
        return childNode;
    }

    public void AddFirstSibling(Node<T> childNode)
    {
        Parent.AddFirstChild(childNode);
    }
    public Node<T> AddLastSibling(T value)
    {
        var childNode = new Node<T>(value);
        AddLastSibling(childNode);
        return childNode;
    }

    public void AddLastSibling(Node<T> childNode)
    {
        Parent.Add(childNode);
    }

    public Node<T> AddParent(T value)
    {
        var newNode = new Node<T>(value);
        AddParent(newNode);
        return newNode;
    }

    public void AddParent(Node<T> parentNode)
    {
        if (!IsRoot)
        {
            throw new ArgumentException("This node [{0}] already has a parent".FormatInvariant(Value), "parentNode");
        }
        parentNode.Add(this);
    }

    public IEnumerable<Node<T>> Ancestors
    {
        get
        {
            if (IsRoot)
            {
                return Enumerable.Empty<Node<T>>();
            }
            return Parent.ToIEnumarable().Concat(Parent.Ancestors);
        }
    }

    public IEnumerable<Node<T>> Descendants
    {
        get
        {
            return SelfAndDescendants.Skip(1);
        }
    }


    public IEnumerable<Node<T>> Children
    {
        get
        {
            return _children;
        }
    }

    public IEnumerable<Node<T>> Siblings
    {
        get
        {
            return SelfAndSiblings.Where(Other);

        }
    }

    private bool Other(Node<T> node)
    {
        return !ReferenceEquals(node, this);
    }

    public IEnumerable<Node<T>> SelfAndChildren
    {
        get
        {
            return this.ToIEnumarable().Concat(Children);
        }
    }

    public IEnumerable<Node<T>> SelfAndAncestors
    {
        get
        {
            return this.ToIEnumarable().Concat(Ancestors);
        }
    }

    public IEnumerable<Node<T>> SelfAndDescendants
    {
        get
        {
            return this.ToIEnumarable().Concat(Children.SelectMany(c => c.SelfAndDescendants));
        }
    }

    public IEnumerable<Node<T>> SelfAndSiblings
    {
        get
        {
            if (IsRoot)
            {
                return this.ToIEnumarable();
            }
            return Parent.Children;

        }
    }

    public IEnumerable<Node<T>> All
    {
        get
        {
            return Root.SelfAndDescendants;
        }
    }


    public IEnumerable<Node<T>> SameLevel
    {
        get
        {
            return SelfAndSameLevel.Where(Other);

        }
    }

    public int Level
    {
        get
        {
            return Ancestors.Count();
        }
    }

    public IEnumerable<Node<T>> SelfAndSameLevel
    {
        get
        {
            return GetNodesAtLevel(Level);
        }
    }

    public IEnumerable<Node<T>> GetNodesAtLevel(int level)
    {
        return Root.GetNodesAtLevelInternal(level);
    }

    private IEnumerable<Node<T>> GetNodesAtLevelInternal(int level)
    {
        if (level == Level)
        {
            return this.ToIEnumarable();
        }
        return Children.SelectMany(c => c.GetNodesAtLevelInternal(level));
    }

    public Node<T> Root
    {
        get
        {
            return SelfAndAncestors.Last();
        }
    }

    public void Disconnect()
    {
        if (IsRoot)
        {
            throw new InvalidOperationException("The root node [{0}] can not get disconnected from a parent.".FormatInvariant(Value));
        }
        Parent._children.Remove(this);
        Parent = null;
    }

    public bool IsRoot
    {
        get { return Parent == null; }
    }

    IEnumerator<T> IEnumerable<T>.GetEnumerator()
    {
        return _children.Values().GetEnumerator();
    }

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

    public IEnumerator<Node<T>> GetEnumerator()
    {
        return _children.GetEnumerator();
    }

    public override string ToString()
    {
        return Value.ToString();
    }

    public static IEnumerable<Node<T>> CreateTree<TId>(IEnumerable<T> values, Func<T, TId> idSelector, Func<T, TId?> parentIdSelector)
        where TId : struct
    {
        var valuesCache = values.ToList();
        if (!valuesCache.Any())
            return Enumerable.Empty<Node<T>>();
        T itemWithIdAndParentIdIsTheSame = valuesCache.FirstOrDefault(v => IsSameId(idSelector(v), parentIdSelector(v)));
        if (itemWithIdAndParentIdIsTheSame != null) // Hier verwacht je ook een null terug te kunnen komen
        {
            throw new ArgumentException("At least one value has the samen Id and parentId [{0}]".FormatInvariant(itemWithIdAndParentIdIsTheSame));
        }

        var nodes = valuesCache.Select(v => new Node<T>(v));
        return CreateTree(nodes, idSelector, parentIdSelector);

    }

    public static IEnumerable<Node<T>> CreateTree<TId>(IEnumerable<Node<T>> rootNodes, Func<T, TId> idSelector, Func<T, TId?> parentIdSelector)
        where TId : struct
    {
        var rootNodesCache = rootNodes.ToList();
        var duplicates = rootNodesCache.Duplicates(n => n).ToList();
        if (duplicates.Any())
        {
            throw new ArgumentException("One or more values contains {0} duplicate keys. The first duplicate is: [{1}]".FormatInvariant(duplicates.Count, duplicates[0]));
        }

        foreach (var rootNode in rootNodesCache)
        {
            var parentId = parentIdSelector(rootNode.Value);
            var parent = rootNodesCache.FirstOrDefault(n => IsSameId(idSelector(n.Value), parentId));

            if (parent != null)
            {
                parent.Add(rootNode);
            }
            else if (parentId != null)
            {
                throw new ArgumentException("A value has the parent ID [{0}] but no other nodes has this ID".FormatInvariant(parentId.Value));
            }
        }
        var result = rootNodesCache.Where(n => n.IsRoot);
        return result;
    }


    protected static bool IsSameId<TId>(TId id, TId? parentId)
        where TId : struct
    {
        return parentId != null && id.Equals(parentId.Value);
    }

    #region Equals en ==

    public static bool operator ==(Node<T> value1, Node<T> value2)
    {
        if ((object)(value1) == null && (object)value2 == null)
        {
            return true;
        }
        return ReferenceEquals(value1, value2);
    }

    public static bool operator !=(Node<T> value1, Node<T> value2)
    {
        return !(value1 == value2);
    }

    public override bool Equals(Object anderePeriode)
    {
        var valueThisType = anderePeriode as Node<T>;
        return this == valueThisType;
    }

    public bool Equals(Node<T> value)
    {
        return this == value;
    }

    public bool Equals(Node<T> value1, Node<T> value2)
    {
        return value1 == value2;
    }

    bool IEqualityComparer.Equals(object value1, object value2)
    {
        var valueThisType1 = value1 as Node<T>;
        var valueThisType2 = value2 as Node<T>;

        return Equals(valueThisType1, valueThisType2);
    }

    public int GetHashCode(object obj)
    {
        return GetHashCode(obj as Node<T>);
    }

    public override int GetHashCode()
    {
        return GetHashCode(this);
    }

    public int GetHashCode(Node<T> value)
    {
        return base.GetHashCode();
    }
    #endregion
}

and in Controller I Try To format this class list to Json

var treeView = Node<ControlType>.CreateTree(_controlTypeBll.GetAll(), c => c.Id, c => c.ParrentId);

var res = JsonConvert.SerializeObject(treeView);

and All I Get in res variable is this " [[],[],[[][]]....". I have used DataContract and DataMember Attribute to Prevent Serializing some properties but the result is same

3
  • Have you filled your Node with any data prior to serializing it? Commented May 4, 2015 at 12:38
  • Yes I Have Filled it Commented May 4, 2015 at 12:39
  • 2
    It would have been better if your question included a Minimal, Complete, and Verifiable example of your problem. It lacks 1) the declaration of your class Node<T>; 2) A definition for your value type ControlType; 3) Various extension methods including FormatInvariant, ToIEnumarable, Duplicates and IEnumerable<T> Values<T>(this IEnumerable<Node<T>> nodes). Commented May 4, 2015 at 17:14

1 Answer 1

0

Your question does not include the declaration of your Node<T> class. From the rest of the (large) class, I reckon it must be something like:

public class Node<T> : IEqualityComparer, IEnumerable<T>

And this explains your problem:

  1. Your class implements IEnumerable<T> for some T.
  2. Json.NET serializes any IEnumerable as a JSON array.
  3. JSON arrays (according to the standard) do not support named properties.
  4. Thus your Value property is not serialized.

If you wish to continue making your Node<T> implement IEnumerable, you need to create a custom JsonConverter for it:

public static class TypeExtensions
{
    public static IEnumerable<Type> BaseTypesAndSelf(this Type type)
    {
        while (type != null)
        {
            yield return type;
            type = type.BaseType;
        }
    }
}

public class NodeConverter : JsonConverter
{
    class NodeWrapper<T>
    {
        public T value { get; set; }
        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
        public IEnumerable<Node<T>> children { get; set; }
    }

    static Type GetNodeValueType(Type type)
    {
        return type.BaseTypesAndSelf().Where(t => t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Node<>)).Select(t => t.GetGenericArguments()[0]).FirstOrDefault();
    }

    public override bool CanConvert(Type objectType)
    {
        return GetNodeValueType(objectType) != null;
    }

    object ReadJsonGeneric<T>(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var wrapper = serializer.Deserialize<NodeWrapper<T>>(reader);
        if (wrapper == null)
            return existingValue;
        var node = existingValue as Node<T> ?? new Node<T>(wrapper.value);
        node.Value = wrapper.value;
        if (wrapper.children != null)
            foreach (var child in wrapper.children)
                node.Add(child);
        return node;
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var method = GetType().GetMethod("ReadJsonGeneric", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);
        var genericMethod = method.MakeGenericMethod(new[] { GetNodeValueType(objectType) });
        return genericMethod.Invoke(this, new object[] { reader, objectType, existingValue, serializer });
    }

    void WriteJsonGeneric<T>(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var node = (Node<T>)value;
        serializer.Serialize(writer, new NodeWrapper<T> { value = node.Value, children = (node.Children.Any() ? node.Children : null)});
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var method = GetType().GetMethod("WriteJsonGeneric", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);
        var genericMethod = method.MakeGenericMethod(new[] { GetNodeValueType(value.GetType()) });
        genericMethod.Invoke(this, new object[] { writer, value, serializer });
    }
}

By calling your Add(Node<T> child) method, the converter also makes sure the parent back-references are set.

And then use it like:

[JsonConverter(typeof(NodeConverter))]
public class Node<T> : IEqualityComparer, IEnumerable<T>
{
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.