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

时间:2019-02-21 19:53:24

标签: c# json.net json-deserialization json-serialization

我具有以下课程结构

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"
}

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

4 个答案:

答案 0 :(得分:2)

实现此目标的一种方法是将Custom JsonConverterJsonConverterAttribute一起使用。例如,您可以为您的课程创建一个自定义转换器:

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的{​​{1}}方法:

SecondClassConverter

提供所需的JSON结果:

enter image description here


使用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(); } 的{​​{1}}方法,反序列化也将起作用:

ReadJson

提供的输出为:

enter image description here

答案 1 :(得分:0)

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

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

然后您可以序列化它。

答案 2 :(得分:0)

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

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

答案 3 :(得分:0)

您有两种选择,一种是@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>();