C# 使用JSON.NET对复杂对象进行序列化和反序列化

C# 使用JSON.NET对复杂对象进行序列化和反序列化,c#,asp.net,serialization,json.net,deserialization,C#,Asp.net,Serialization,Json.net,Deserialization,我在使用JSON.NET转换器和ASP.NET WebApi时遇到了一个问题。下面是该场景的表示 属性类可以是Parent类型或Measurement类型,并具有所述属性的序列化性质 [DataContract] [JsonConverter(typeof(AttributeConverter))] public abstract class Attribute { [DataMember] public string Id { get; set; } [DataMem

我在使用JSON.NET转换器和ASP.NET WebApi时遇到了一个问题。下面是该场景的表示

属性类可以是Parent类型或Measurement类型,并具有所述属性的序列化性质

[DataContract]
[JsonConverter(typeof(AttributeConverter))]    
public abstract class Attribute
{

    [DataMember] public string Id { get; set; }
    [DataMember] public string DisplayLabel { get; set; }
}

[DataContract]
public class Parent : Attribute
{
    [DataMember] public List<Attribute> Attributes { get; set; }
}

[DataContract]
public class Measurement : Attribute
{
    [DataMember] public Bound Bounds { get; set; }
    [DataMember] public int measurementValue { get; set; }
}
根据我们的要求,我需要一个标识符来指定属性的类型,该属性与“$type”提供的属性相同。我们已经编写了一个自定义转换器,它将在序列化期间引入AttributeKind信息,并在反序列化期间使用我的转换器的ReadJson()进行恢复。代码片段如下所示

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
   writer.WriteStartObject();
   writer.WritePropertyName("AttributeKind");

   AttributeKind type = (AttributeKind)System.Enum.Parse(typeof(AttributeKind), value.GetType().Name);
   writer.WriteValue(type);

   var props = value.GetType().GetProperties();
   foreach (var propertyInfo in props)
   {
       var tempVal = propertyInfo.GetValue(value, null);
       if (tempVal == null) continue;

       writer.WritePropertyName(propertyInfo.Name);
       serializer.Serialize(writer, tempVal);
    }
    writer.WriteEndObject();
}

public override object ReadJson(JsonReader reader, System.Type objectType, object existingValue, JsonSerializer serializer)
{
    JObject jObject = serializer.Deserialize<JObject>(reader);

    JProperty jProperty = jObject.Properties().FirstOrDefault(p => p.Name == "AttributeKind");

    if (jProperty == null)
        return null;

    JValue value = jProperty.Value as JValue;

    AttributeKind attributeKind = (AttributeKind)System.Enum.Parse(typeof(AttributeKind), value.Value.ToString());

    Attribute attribute = null;
    switch (attributeKind)
    {
        case AttributeKind.ParentAttribute:
            attribute = new ParentAttribute();
            break;

        case AttributeKind.MeasurementAttribute:
            attribute = new MeasurementAttribute();
            break;
    }

    var props = attribute.GetType().GetProperties();
    foreach (var propertyInfo in props)
    {
        jProperty = jObject.Properties().FirstOrDefault(p => p.Name == propertyInfo.Name);
        if (jProperty != null)
        {
            JValue jValue = jProperty.Value as JValue;

            if (jValue != null)
            {
                object dataValue = null;
                if (jValue.Type == JTokenType.Integer)
                    dataValue = System.Convert.ToInt32(jValue.Value);
                else
                    dataValue = jValue.Value;

                propertyInfo.SetValue(attribute, dataValue, null);
            }
        }
    }
    return attribute;
}
public override void WriteJson(JsonWriter编写器、对象值、JsonSerializer序列化器)
{
writer.WriteStartObject();
writer.WritePropertyName(“AttributeKind”);
AttributeKind type=(AttributeKind)System.Enum.Parse(typeof(AttributeKind),value.GetType().Name);
writer.WriteValue(类型);
var props=value.GetType().GetProperties();
foreach(道具中的var propertyInfo)
{
var tempVal=propertyInfo.GetValue(值,null);
如果(tempVal==null)继续;
writer.WritePropertyName(propertyInfo.Name);
serializer.Serialize(writer,tempVal);
}
writer.WriteEndObject();
}
公共重写对象ReadJson(JsonReader阅读器、System.Type对象类型、对象existingValue、JsonSerializer序列化程序)
{
JObject JObject=序列化程序。反序列化(读取器);
JProperty JProperty=jObject.Properties().FirstOrDefault(p=>p.Name==“AttributeKind”);
如果(jProperty==null)
返回null;
JValue value=jProperty.value作为JValue;
AttributeKind AttributeKind=(AttributeKind)System.Enum.Parse(typeof(AttributeKind),value.value.ToString());
属性=null;
开关(属性绑定)
{
案例属性kind.ParentAttribute:
属性=新的ParentAttribute();
打破
案例属性kind.MeasurementAttribute:
属性=新的度量属性();
打破
}
var props=attribute.GetType().GetProperties();
foreach(道具中的var propertyInfo)
{
jProperty=jObject.Properties().FirstOrDefault(p=>p.Name==propertyInfo.Name);
如果(jProperty!=null)
{
JValue JValue=jProperty.Value作为JValue;
if(jValue!=null)
{
对象数据值=null;
if(jValue.Type==JTokenType.Integer)
dataValue=System.Convert.ToInt32(jValue.Value);
其他的
dataValue=jValue.Value;
propertyInfo.SetValue(属性,数据值,null);
}
}
}
返回属性;
}
以下是在反序列化响应中观察到的问题:

  • 如果是ParentType属性,则为空的属性列表,其中序列化的输入包含元素
  • Bounds属性尚未填充,返回null
  • 我无法继续前进,因为我似乎不完全了解JsonConverters是如何被拦截的,以及在存在转换器链的情况下拦截是如何发生的(即,2个转换器..一个用于类,另一个用于复杂属性)

    非常感谢您的帮助?谢谢

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
       writer.WriteStartObject();
       writer.WritePropertyName("AttributeKind");
    
       AttributeKind type = (AttributeKind)System.Enum.Parse(typeof(AttributeKind), value.GetType().Name);
       writer.WriteValue(type);
    
       var props = value.GetType().GetProperties();
       foreach (var propertyInfo in props)
       {
           var tempVal = propertyInfo.GetValue(value, null);
           if (tempVal == null) continue;
    
           writer.WritePropertyName(propertyInfo.Name);
           serializer.Serialize(writer, tempVal);
        }
        writer.WriteEndObject();
    }
    
    public override object ReadJson(JsonReader reader, System.Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject jObject = serializer.Deserialize<JObject>(reader);
    
        JProperty jProperty = jObject.Properties().FirstOrDefault(p => p.Name == "AttributeKind");
    
        if (jProperty == null)
            return null;
    
        JValue value = jProperty.Value as JValue;
    
        AttributeKind attributeKind = (AttributeKind)System.Enum.Parse(typeof(AttributeKind), value.Value.ToString());
    
        Attribute attribute = null;
        switch (attributeKind)
        {
            case AttributeKind.ParentAttribute:
                attribute = new ParentAttribute();
                break;
    
            case AttributeKind.MeasurementAttribute:
                attribute = new MeasurementAttribute();
                break;
        }
    
        var props = attribute.GetType().GetProperties();
        foreach (var propertyInfo in props)
        {
            jProperty = jObject.Properties().FirstOrDefault(p => p.Name == propertyInfo.Name);
            if (jProperty != null)
            {
                JValue jValue = jProperty.Value as JValue;
    
                if (jValue != null)
                {
                    object dataValue = null;
                    if (jValue.Type == JTokenType.Integer)
                        dataValue = System.Convert.ToInt32(jValue.Value);
                    else
                        dataValue = jValue.Value;
    
                    propertyInfo.SetValue(attribute, dataValue, null);
                }
            }
        }
        return attribute;
    }