将包含对象属性的poco序列化为Json

本文关键字:序列化 Json poco 包含 对象 属性 | 更新日期: 2023-09-27 17:49:35

我有一个类,我需要序列化传递给另一个系统。

类包含一个定义为对象的属性,因为对象包含的类的类型在运行时可能会变化。

我的类看起来像这样的简化模型;

public class MyTestXML
{
    public string String1 { get; set; }
    public string String2 { get; set; }
    [System.Xml.Serialization.XmlElementAttribute("First", typeof(MyFirstObject),
                              Form = System.Xml.Schema.XmlSchemaForm.Qualified)]
    [System.Xml.Serialization.XmlElementAttribute("Second", typeof(MySecondObject),
                              Form = System.Xml.Schema.XmlSchemaForm.Qualified)]
    public object MyObject { get; set; }
}
public class MyFirstObject
{
    public string theFirstObjectString { get; set; }
}
public class MySecondObject
{
    public string theSecondObjectString { get; set; }
}

这个类通过使用XmlElementAttribute和XmlSerializer完美地序列化为xml,但是当我尝试将它序列化为Json(使用Newtonsoft Json.Net)时,对象是一个未定义的类型,并且不能反序列化。

是否有一种方法来指定XmlElementAttribute在Json属性实现序列化时相同的结果?

我想为序列化对象提供Json的使用,因为它是xml大小的一半,但除非我能解决对象属性的序列化问题,否则不能。

将包含对象属性的poco序列化为Json

您必须创建自己的自定义序列化行为。看看这里的答案:https://stackoverflow.com/a/22722467/2039359关于如何实现自己的Json的JsonConverter。净

你可以这样创建json

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            MyTestXML myTestXml = (MyTestXML) value;
            JObject jObject = JObject.FromObject(value);
            JProperty prop = jObject.Children<JProperty>().First(p=>p.Name.Contains("MyObject"));
            if (myTestXml.MyObject.GetType() == typeof (MyFirstObject))
            {
                prop.AddAfterSelf(new JProperty("First", JToken.FromObject(myTestXml.MyObject)));
                prop.Remove();
                jObject.WriteTo(writer);
            }
            else if (myTestXml.MyObject.GetType() == typeof (MySecondObject))
            {
                prop.AddAfterSelf(new JProperty("Second", JToken.FromObject(myTestXml.MyObject)));
                prop.Remove();
                jObject.WriteTo(writer);                    
            }
        }

当你反序列化

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            JObject jo = JObject.Load(reader);
            MyTestXML myTestXml = new MyTestXML();
            serializer.Populate(jo.CreateReader(), myTestXml);
            object myObject = null;
            if (jo["First"] != null)
            {
                myObject = new MyFirstObject { TheFirstObjectString = jo["First"].SelectToken(@"TheFirstObjectString").Value<string>() };
            }
            if (jo["Second"] != null)
            {
                myObject = new MySecondObject { TheSecondObjectString = jo["Second"].SelectToken(@"TheSecondObjectString").Value<string>() };
            }
            myTestXml.MyObject = myObject;
            return myTestXml;
        }

要使用它,您可以在序列化/反序列化时提供JsonConverter,如下所示:

        var settings = new JsonSerializerSettings();
        settings.Converters.Add(new MyTextXmlJsonConverter());
        var a = JsonConvert.SerializeObject(myTestXml, settings);

希望这就是你要找的

另一种选择是创建一个自定义契约解析器,它允许您检测应用了哪个xml属性。如果你需要特定的输出,你可以在属性上应用一个自定义的JsonConverter。

public class CustomContractResolver : DefaultContractResolver
{
    private readonly JsonMediaTypeFormatter formatter;
    public CustomContractResolver(JsonMediaTypeFormatter formatter)
    {
        this.formatter = formatter;
    }
    public JsonMediaTypeFormatter Formatter
    {
        [DebuggerStepThrough]
        get { return this.formatter; }
    }
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        JsonProperty property = base.CreateProperty(member, memberSerialization);
        this.ConfigureProperty(member, property);
        return property;
    }
    private void ConfigureProperty(MemberInfo member, JsonProperty property)
    {
        if (Attribute.IsDefined(member, typeof(XmlElementAttribute), true))
        {
            var attribute = member.CustomAttributes.Where(x => x.AttributeType == typeof(XmlElementAttribute)).First();
            // do something with your attribute here like apply a converter
            property.Converter = new XmlAttributeJsonConverter();
        }            
    }
}