private string GetXmlNodeName(Type type, LinkedNode<object> ancestors, PropertyInfo sourceProperty, Type itemType) { return sourceProperty != null && itemType == null ? sourceProperty.GetXmlName() : (sourceProperty.GetXmlArrayItemName() ?? type.GetXmlName(_options.GenericTypeXmlNameFormat, _options.GenericListXmlNameFormat, !ancestors.Any())); }
private static string GetJsonNodeName(LinkedNode<object> ancestors, PropertyInfo sourceProperty, Type itemType) { return !ancestors.Any() ? "root" : (itemType != null ? "item" : sourceProperty.GetXmlName()); }
private void AddNamespaces(Format format, LinkedNode<object> ancestors, ValueNode valueNode) { if (format == Format.Xml && !ancestors.Any()) _options.XmlNamespaces.ForEach(x => valueNode.XmlElement.Add(new XAttribute(XNamespace.Xmlns + x.Key, x.Value))); }
private XObject Traverse(Format format, object source, LinkedNode<object> ancestors, PropertyInfo sourceProperty = null, Type itemType = null) { var type = itemType ?? (sourceProperty == null ? source.GetType() : sourceProperty.PropertyType); var name = format == Format.Xml ? GetXmlNodeName(type, ancestors, sourceProperty, itemType) : GetJsonNodeName(ancestors, sourceProperty, itemType); Func<object, XElement> createElement = x => new XElement(_options.DefaultNamespace == null || format == Format.Json ? name : _options.DefaultNamespace + name, x, format == Format.Json ? new XAttribute("type", "object") : null); Func<string, XObject> createValueNode = x => _options.XmlValueNodeType == XmlValueNodeType.Attribute || (sourceProperty != null && sourceProperty.HasCustomAttribute<XmlAttributeAttribute>()) ? new XAttribute(name, x ?? "") : (XObject)createElement(x); XObject node; ValueNode valueNode = null; if (_options.ValueWriters.ContainsKey(type)) { node = createValueNode(null); valueNode = new ValueNode(node, format); if (format == Format.Json) valueNode.JsonField.DataType = source.ToJsonValueType(); _options.ValueWriters[type](new WriterContext(_options, sourceProperty, source, valueNode)); } else if (type.IsSimpleType()) { node = source == null ? createValueNode(null) : createValueNode(source.ToString()); valueNode = new ValueNode(node, format); if (format == Format.Json) valueNode.JsonField.DataType = source.ToJsonValueType(); } else if (source == null) { node = createElement(null); valueNode = new ValueNode(node, format); if (format == Format.Json) valueNode.JsonField.DataType = JsonDataType.Null; } else if (type.IsEnumerable()) { var listItemType = type.GetGenericEnumerableType(); node = createElement(null).WithChildren(source.AsEnumerable().Select(x => Traverse(format, x, ancestors.Add(source), sourceProperty, listItemType ?? x.GetType()))); valueNode = new ValueNode(node, format); if (format == Format.Json) valueNode.JsonField.DataType = JsonDataType.Array; } else { node = createElement(null); var properties = type.GetSerializableProperties(_options.ExcludedTypes); foreach (var property in properties.Where(x => !x.IsIgnored())) { var propertyValue = property.GetValue(source, null); if ((propertyValue == null && _options.ExcludeNullValues) || ancestors.Any(propertyValue)) continue; ((XElement)node).Add(Traverse(format, propertyValue, ancestors.Add(propertyValue), property)); } } valueNode = valueNode ?? new ValueNode(node, format); AddNamespaces(format, ancestors, valueNode); _options.NodeWriters.ForEach(x => x(new WriterContext(_options, sourceProperty, source, valueNode))); return valueNode.Object; }