反序列化JSON序列化对象的JSON列表

时间:2016-06-19 14:40:34

标签: c# json serialization json.net

我试图反序列化List<string>,其实际上是List<myClass>,其对象已被序列化。例如:

static void Main(string[] args)
{
    List<MyThirdClass> myThirdClass = new List<MyThirdClass>(new[] { new MyThirdClass { RoleId = 123, RoleName = "123" }, new MyThirdClass { RoleId = 234, RoleName = "234" } });
    List<MySecondSerializedClass> mySecondSerializedClass = new List<MySecondSerializedClass>();
    foreach (MyThirdClass thirdClass in myThirdClass)
    {
        MySecondSerializedClass secondClass = new MySecondSerializedClass { Roles = new List<string>() };
        foreach (MyThirdClass tClass in myThirdClass)
        {
            secondClass.Roles.Add(JsonConvert.SerializeObject(tClass));
        }
        mySecondSerializedClass.Add(secondClass);
    }
    MyFirstSerializedClass firstClass = new MyFirstSerializedClass
    {
        Id = 1,
        Name = "1",
        Roles = mySecondSerializedClass
    };

    string serializedFirstClass = JsonConvert.SerializeObject(firstClass, Formatting.Indented);
    MyFirstNonSerializedClass nonSerializedFirstClass = JsonConvert.DeserializeObject<MyFirstNonSerializedClass>(serializedFirstClass);
}

public class MyFirstSerializedClass
{
    public int Id { get; set; }
    public string Name { get; set; }
    public List<MySecondSerializedClass> Roles { get; set; }
}

public class MyFirstNonSerializedClass
{
    public int Id { get; set; }
    public string Name { get; set; }
    public List<MySecondNonSerializedClass> Roles { get; set; }
}

public class MySecondSerializedClass
{
    public List<string> Roles { get; set; }
}

public class MySecondNonSerializedClass
{
    public List<MyThirdClass> Roles { get; set; }
}

public class MyThirdClass
{
    public int RoleId { get; set; }
    public string RoleName { get; set; }
}

serializedFirstClass会返回这样的JSON:

{
  "Id": 1,
  "Name": "1",
  "Roles": [
    {
      "Roles": [
        "{\"RoleId\":123,\"RoleName\":\"123\"}",
        "{\"RoleId\":234,\"RoleName\":\"234\"}"
      ]
    },
    {
      "Roles": [
        "{\"RoleId\":123,\"RoleName\":\"123\"}",
        "{\"RoleId\":234,\"RoleName\":\"234\"}"
      ]
    }
  ]
}

尝试对其进行反序列化会抛出一条带有消息的异常:

  

转换价值时出错&#34; {&#34; RoleId&#34;:123,&#34; RoleName&#34;:&#34; 123&#34;}&#34;输入&#39; ConsoleApplication1.Program + MyThirdClass&#39;。路径&#39;角色[0] .Roles [0]&#39;,第7行,第47位。

我做错了什么或以任何方式将MyFirstSerializedClass递归反序列化为MyFirstNonSerializedClass?

3 个答案:

答案 0 :(得分:1)

您希望将string反序列化为MyThirdClass结构,这是不可能的。

他们实际上并不相同。

字符串列表将序列化为

<强> “ \” SomeProperty \ “:\” SomePropertyValue \ “的下,
\” SomeProperty2 \ “:\” SomePropertyValue \ “的

CustomClass列表

“SomeProperty”: “SomePropertyValue”,
“SomeProperty2”: “SomeProperty2Value”

答案 1 :(得分:1)

序列化时,将MyThirdClass转换为字符串。 反序列化时需要逆变换。添加从字符串到您的类型的隐式转换。

public static implicit operator MyThirdClass(string s)
{
  // when serializing indented =>
  // return JsonConvert.DeserializeObject<B3>(s, new JsonSerializerSettings() { Formatting = Formatting.Indented});
  // otherwise
  return JsonConvert.DeserializeObject<B3>(s);
}

答案 2 :(得分:1)

您可以使用一组类和一个MyThirdClass的可选JsonConverter来执行此操作,该MyThirdClass将当前JSON标记读取为字符串文字,然后使用嵌套的序列化程序从JSON反序列化该字符串文字作为public class MyFirstClass { public int Id { get; set; } public string Name { get; set; } public List<MySecondClass> Roles { get; set; } } public class MySecondClass { public List<MyThirdClass> Roles { get; set; } } public class MyThirdClass { public int RoleId { get; set; } public string RoleName { get; set; } } public sealed class MyThirdClassStringConverter : JsonConverter { readonly JsonSerializerSettings settings; public MyThirdClassStringConverter() : this(null) { } public MyThirdClassStringConverter(JsonSerializerSettings settings) { this.settings = settings; } JsonSerializer GetInnerSerializer() { var innerSerializer = JsonSerializer.CreateDefault(settings); for (int i = innerSerializer.Converters.Count - 1; i >= 0; i--) if (innerSerializer.Converters[i] is MyThirdClassStringConverter) innerSerializer.Converters.RemoveAt(i); return innerSerializer; } public override bool CanConvert(Type objectType) { return typeof(MyThirdClass).IsAssignableFrom(objectType); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) return null; var innerSerializer = GetInnerSerializer(); if (reader.TokenType == JsonToken.String) { var s = reader.Value.ToString(); using (var innerReader = new StringReader(s)) return innerSerializer.Deserialize(innerReader, objectType); } else { return innerSerializer.Deserialize(reader, objectType); } } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { var innerSerializer = GetInnerSerializer(); var sb = new StringBuilder(); using (var innerWriter = new StringWriter(sb)) innerSerializer.Serialize(innerWriter, value); writer.WriteValue(sb.ToString()); } } 的一个实例。如果要将类序列化或反序列化为嵌入字符串,请将转换器添加到JsonSerializerSettings.Converters;将它作为对象序列化。

因此:

var stringSettings = new JsonSerializerSettings { Converters = new[] { new MyThirdClassStringConverter() } };

// Deserialize JSON where MyThirdClass objects are embedded strings
var root = JsonConvert.DeserializeObject<MyFirstClass>(stringJson, stringSettings);

// Re-serialize to JSON where MyThirdClass objects are objects
var newNonStringJson = JsonConvert.SerializeObject(root, Formatting.Indented);
// Re-serialize to JSON where MyThirdClass objects are embedded strings
var newStringJson = JsonConvert.SerializeObject(root, Formatting.Indented, stringSettings);

然后,按如下方式使用:

MyThirdClass

请注意,转换器应直接使用[JsonConverter(typeof(MyThirdClassStringConverter))]应用于ReadJson(),因为会产生无限递归。转换器的SysAllocString方法测试当前令牌是字符串还是对象并相应地进行调整,因此它可以用于以任一格式反序列化JSON。

示例fiddle