繁体   English   中英

Newtonsoft Json序列化/反序列化嵌套属性

[英]Newtonsoft Json Serialize/Deserialize nested property

我有以下课程结构

public class MainClass
{
   public string MyStringValue {get;set;}
   public SecondClass MyClassValue {get;set;}
}

public class SecondClass
{
   public string Value {get;set;}
}

我设置以下值:

SecondClass secondClass = new SecondClass
{
   Value = "Test"
}

MainClass mainClass = new MainClass
{
   MyStringValue = "String Value",
   MyClassValue = secondClass
}

当我序列化类“ mainClass”时,我得到以下Json(对我来说这是绝对清楚的):

{
  "MyStringValue":"String Value",
  "MyClassValue":
  {
     "Value":"Test"
  }
}

在某些情况下,我需要序列化为以下内容:

{
  "MyStringValue":"String Value",
  "MyClassValue": "Test"
}

子类的字段名称始终为“ Value”,该怎么做? (我还需要对相同结构进行反序列化)

实现此目的的一种方法是使用带有JsonConverterAttributeCustom JsonConverter 例如,您可以为您的课程创建一个自定义转换器:

public class SecondClassConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(SecondClass);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        try
        {
            if (reader.TokenType == JsonToken.String)
            {
                return new SecondClass
                {
                    Value = reader.Value.ToString()
                };
            }
        }
        catch (Exception ex)
        {
            throw new JsonSerializationException($"Error converting value {reader.Value} to type '{objectType}'.", ex);
        }

        throw new JsonSerializationException($"Unexpected token {reader.TokenType} when parsing {nameof(SecondClass)}.");
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        if (value == null)
        {
            writer.WriteNull();
            return;
        }

        var secondClass = (SecondClass)value;
        writer.WriteValue(secondClass.Value);
    }
}

然后将JsonConverterAttribute与该转换器一起使用:

public class MainClass
{
    public string MyStringValue { get; set; }
    [JsonConverter(typeof(SecondClassConverter))]
    public SecondClass MyClassValue { get; set; }
}

public class SecondClass
{
    public string Value { get; set; }
}

然后,这将允许所有序列化MainClass使用WriteJson的方法SecondClassConverter

static void Main(string[] args)
{
    SecondClass secondClass = new SecondClass
    {
        Value = "Test"
    };

    MainClass mainClass = new MainClass
    {
        MyStringValue = "String Value",
        MyClassValue = secondClass
    };

    var json = JsonConvert.SerializeObject(mainClass);

    Console.WriteLine(json);
    Console.ReadLine();
}

提供所需的JSON结果:

在此处输入图片说明


和反序列化也将工作,利用ReadJson的方法SecondClassConverter

static void Main(string[] args)
{
    var json = "{ \"MyStringValue\":\"String Value\", \"MyClassValue\": \"Test\" }";

    var decodedJson = JsonConvert.DeserializeObject<MainClass>(json);

    Console.WriteLine($"decodedJson.MyStringValue: {decodedJson.MyStringValue}");
    Console.WriteLine($"decodedJson.MyClassValue.Value: {decodedJson.MyClassValue.Value}");
    Console.ReadLine();
}

提供的输出为:

在此处输入图片说明

上方的json与后者不同。 未经转换{"MyStringValue":"String Value","MyClassValue": "Test"}主类无法序列化为{"MyStringValue":"String Value","MyClassValue": "Test"}

var resultObjet = new { 
     MyStringValue = mainClass.MyStringValue,
     MyClassValue = mainClass.SecondClass.MyClassValue
}

然后您可以序列化它。

为了做到这一点,您需要一个新的反序列化类。 但是,对于序列化,您可以即时创建一个匿名类型,如下所示:

void Main()
{
    // import Newtonsoft.JsonConvert

    SecondClass secondClass = new SecondClass
    {
        Value = "Test"
    };

    MainClass mainClass = new MainClass
    {
        MyStringValue = "String Value",
        MyClassValue = secondClass
    };

    // The JSON as you expect
    var origJson = JsonConvert.SerializeObject(mainClass);
    Console.WriteLine(origJson);
    // The JSON Deserialized and the second class value outputted
    Console.WriteLine(JsonConvert.DeserializeObject<MainClass>(origJson).MyClassValue.Value);

    // The modified JSON as you wanted it
    var modJson = JsonConvert.SerializeObject(new { mainClass.MyStringValue, MyClassValue = mainClass.MyClassValue.Value });
    Console.WriteLine(modJson);

    // The modified JSON deserialized
    var deserialized = JsonConvert.DeserializeObject<ModMainClass>(modJson);
    Console.WriteLine(deserialized.MyStringValue);
}

public class ModMainClass
{
    public string MyStringValue { get; set; }
    public string MyClassValue { get; set; }
}

public class MainClass
{
   public string MyStringValue {get;set;}
   public SecondClass MyClassValue {get;set;}
}

public class SecondClass
{
    public string Value { get; set; }
} 

您有两种选择,一种是@Simonare提到的

或将您的类MainClass的构造方法更改为

public class MainClass<T>
{
    public string MyStringValue { get; set; }
    public T MyClassValue { get; set; }
}

public class SecondClass
{
    public string Value { get; set; }
}

现在您只需选择要用作MyClassValue

var c = new MainClass<string>();

要么

 var c = new MainClass<SecondClass>();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM