Newtonsoft Json Serialize/Deserialize 嵌套 属性

Newtonsoft Json Serialize/Deserialize nested property

我有以下class结构

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
}

当我序列化 class "mainClass" 时,我得到以下 Json (这对我来说绝对清楚):

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

有些情况下我想改为序列化为以下内容:

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

子class的字段名总是"Value",这怎么办? (而且我还需要对相同的结构进行反序列化)

上面的json和后面的不一样。 Main class 不能在没有转换的情况下序列化为 {"MyStringValue":"String Value","MyClassValue": "Test"}

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

然后就可以序列化了

为此,您需要一个新的 class 进行反序列化。但是对于序列化,您可以即时创建一个匿名类型,如下所示:

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提到的

或将 class 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>();

实现此目的的一种方法是使用 Custom JsonConverter with the JsonConverterAttribute。例如,您可以为 class:

创建自定义转换器
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 的所有序列化使用 SecondClassConverterWriteJson 方法:

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 结果:


反序列化也可以,利用SecondClassConverterReadJson方法:

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();
}

提供输出为: