C# .net JSON或XML对象序列化和创建,包括字段类型
我试图将动态DTO映射到JSON或XML,但要获得关于字段类型的信息。 所以我想知道,从这个物体上看,是否有可能:C# .net JSON或XML对象序列化和创建,包括字段类型,c#,.net,xml,json,serialization,C#,.net,Xml,Json,Serialization,我试图将动态DTO映射到JSON或XML,但要获得关于字段类型的信息。 所以我想知道,从这个物体上看,是否有可能: public class AddressDto { public string Street { get; set; } } public class UserInfoDto { public string UserName { get; set; } public int Age {
public class AddressDto
{
public string Street { get; set; }
}
public class UserInfoDto
{
public string UserName { get; set; }
public int Age { get; set; }
public AddressDto Address { get; set; }
}
要在JSON(或XML)中获得类似的内容:
…反之亦然。是的,这是可能的,但您必须做一些工作来指导序列化程序如何格式化输出字符串。如果您想坚持使用内置的.NET序列化程序,可以使用
System.Runtime.Serialization.Json.DataContractJsonSerializer
类来实现这一点
1-创建MetadataObject类作为输出数据的包装器对象
定义以下类并用[DataContract]
标记它,以便可以序列化它:
[DataContract]
public class MetadataObject
{
[DataMember(Name = "fieldType")]
public string FieldType { get; set; }
[DataMember(Name = "fieldName")]
public string FieldName { get; set; }
[DataMember(Name = "fieldValue")]
public object FieldValue { get; set; }
}
2-告诉序列化程序如何序列化父对象(UserInfoDto)
为此,您需要让UserInfoDto
对象实现ISerializable
接口(更具体地说,是GetObjectData()
方法),并将其标记为[Serializable]
。您还需要包含此类将包含的所有自定义类型。在这种情况下,它将是AddressDto
类型,以及List
,在GetObjectData()
方法中构造。最后一个类如下所示:
[KnownType(typeof(AddressDto))]
[KnownType(typeof(List<MetadataObject>))]
[Serializable]
public class UserInfoDto : ISerializable
{
public string UserName { get; set; }
public int Age { get; set; }
public AddressDto Address { get; set; }
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
var nodes = this.GetType().GetProperties().Select(property =>
{
return new MetadataObject
{
FieldType = property.PropertyType.Name,
FieldName = property.Name,
FieldValue = property.GetValue(this, null)
};
}).ToList();
info.AddValue("fieldType", this.GetType().Name);
info.AddValue("objectValue", nodes);
}
}
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(UserInfoDto));
var data = new UserInfoDto { Age = 30, UserName = "John" };
data.Address = new AddressDto { Street = "123 ABC" };
using (MemoryStream stream = new MemoryStream())
{
using (StreamReader reader = new StreamReader(stream))
{
serializer.WriteObject(stream, data);
stream.Position = 0;
var output = reader.ReadToEnd();
}
}
{
"fieldType":"UserInfoDto",
"objectValue":[
{
"__type":"MetadataObject:#StackOverflow.Console",
"fieldName":"UserName",
"fieldType":"String",
"fieldValue":"John"
},
{
"__type":"MetadataObject:#StackOverflow.Console",
"fieldName":"Age",
"fieldType":"Int32",
"fieldValue":30
},
{
"__type":"MetadataObject:#StackOverflow.Console",
"fieldName":"Address",
"fieldType":"AddressDto",
"fieldValue":{
"__type":"AddressDto:#StackOverflow.Console",
"fieldType":"String",
"fieldName":"Street",
"fieldValue":"123 ABC"
}
}
]
}
4-将其全部放在一起
最后,按如下方式定义序列化程序:
[KnownType(typeof(AddressDto))]
[KnownType(typeof(List<MetadataObject>))]
[Serializable]
public class UserInfoDto : ISerializable
{
public string UserName { get; set; }
public int Age { get; set; }
public AddressDto Address { get; set; }
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
var nodes = this.GetType().GetProperties().Select(property =>
{
return new MetadataObject
{
FieldType = property.PropertyType.Name,
FieldName = property.Name,
FieldValue = property.GetValue(this, null)
};
}).ToList();
info.AddValue("fieldType", this.GetType().Name);
info.AddValue("objectValue", nodes);
}
}
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(UserInfoDto));
var data = new UserInfoDto { Age = 30, UserName = "John" };
data.Address = new AddressDto { Street = "123 ABC" };
using (MemoryStream stream = new MemoryStream())
{
using (StreamReader reader = new StreamReader(stream))
{
serializer.WriteObject(stream, data);
stream.Position = 0;
var output = reader.ReadToEnd();
}
}
{
"fieldType":"UserInfoDto",
"objectValue":[
{
"__type":"MetadataObject:#StackOverflow.Console",
"fieldName":"UserName",
"fieldType":"String",
"fieldValue":"John"
},
{
"__type":"MetadataObject:#StackOverflow.Console",
"fieldName":"Age",
"fieldType":"Int32",
"fieldValue":30
},
{
"__type":"MetadataObject:#StackOverflow.Console",
"fieldName":"Address",
"fieldType":"AddressDto",
"fieldValue":{
"__type":"AddressDto:#StackOverflow.Console",
"fieldType":"String",
"fieldName":"Street",
"fieldValue":"123 ABC"
}
}
]
}
运行此操作时,输出
如下所示:
[KnownType(typeof(AddressDto))]
[KnownType(typeof(List<MetadataObject>))]
[Serializable]
public class UserInfoDto : ISerializable
{
public string UserName { get; set; }
public int Age { get; set; }
public AddressDto Address { get; set; }
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
var nodes = this.GetType().GetProperties().Select(property =>
{
return new MetadataObject
{
FieldType = property.PropertyType.Name,
FieldName = property.Name,
FieldValue = property.GetValue(this, null)
};
}).ToList();
info.AddValue("fieldType", this.GetType().Name);
info.AddValue("objectValue", nodes);
}
}
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(UserInfoDto));
var data = new UserInfoDto { Age = 30, UserName = "John" };
data.Address = new AddressDto { Street = "123 ABC" };
using (MemoryStream stream = new MemoryStream())
{
using (StreamReader reader = new StreamReader(stream))
{
serializer.WriteObject(stream, data);
stream.Position = 0;
var output = reader.ReadToEnd();
}
}
{
"fieldType":"UserInfoDto",
"objectValue":[
{
"__type":"MetadataObject:#StackOverflow.Console",
"fieldName":"UserName",
"fieldType":"String",
"fieldValue":"John"
},
{
"__type":"MetadataObject:#StackOverflow.Console",
"fieldName":"Age",
"fieldType":"Int32",
"fieldValue":30
},
{
"__type":"MetadataObject:#StackOverflow.Console",
"fieldName":"Address",
"fieldType":"AddressDto",
"fieldValue":{
"__type":"AddressDto:#StackOverflow.Console",
"fieldType":"String",
"fieldName":"Street",
"fieldValue":"123 ABC"
}
}
]
}
请注意,
\u type
属性由序列化程序自动生成。如果您使用的是.NET 4.5,您可以(如果字符串需要反序列化回对象中,您可能需要它们)是否希望自动执行此操作?因为我脑子里有一个手动的解决方案(实际上很乏味)。自动的会更好。我可以通过手动使用反射生成一些自定义JSON或XML来实现这一点,但当我需要将其转换回源对象时,我遇到了一些问题。因此,如果您有任何解决方案,请随意分享。这是一个很好的解决方案,但我需要它来处理任何自定义数据,我不能这样修改(我不能添加[Serializable]anotation或任何其他更改)。它应该能够处理通过第三方程序集的反射加载的对象。在这种情况下,您需要定义自己的数据协定序列化程序,坦率地说,.NET Json库会让您感到痛苦。看看Json.NET。