gpt4 book ai didi

c# - 反序列化使用 TypeNameHandling.All 序列化的字符串

转载 作者:行者123 更新时间:2023-11-30 23:06:53 27 4
gpt4 key购买 nike

使用以下示例序列化了一个类

using Newtonsoft.Json;
using System;

namespace ConsoleAppCompare
{
class Program
{
static void Main(string[] args)
{
Movie movie = new Movie()
{
Name = "Avengers",
Language = "En",
Actors = new Character[] { new Character(){Name="Phil Coulson"},new Character(){Name="Tony Stark"}
}};
Console.WriteLine(JsonConvert.SerializeObject(movie, Formatting.Indented, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }));
Console.ReadLine();
}
}

class Movie
{

public string Name { get; set; }

public string Language { get; set; }

public Character[] Actors { get; set; }

}

class Character
{
public string Name { get; set; }
}
}

上面的示例生成以下 json

{
"$type": "ConsoleAppCompare.Movie, ConsoleAppCompare",
"Name": "Avengers",
"Language": "En",
"Actors": {
"$type": "ConsoleAppCompare.Character[], ConsoleAppCompare",
"$values": [
{
"$type": "ConsoleAppCompare.Character, ConsoleAppCompare",
"Name": "Phil Coulson"
},
{
"$type": "ConsoleAppCompare.Character, ConsoleAppCompare",
"Name": "Tony Stark"
}
]
}
}

现在,在另一个无法访问上述模型的程序上,
我必须将字符串反序列化为一个对象,但我尝试过的任何操作似乎都不起作用...

为了创建我的新模型,我将 json 复制到剪贴板上并使用了 Visual Studio 的“选择性粘贴”功能

using Newtonsoft.Json;
using System;
using System.IO;


namespace ConsoleAppCompare
{
class Program
{
static void Main(string[] args)
{
var s = File.ReadAllText(@"C:\Users\nvovo\Desktop\asdf\aa.txt");

Rootobject movie = null;

// nothing Works :(
//movie =JsonConvert.DeserializeObject<Rootobject>(s, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All });
//movie = JsonConvert.DeserializeObject<Rootobject>(s, new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.None });
//movie = JsonConvert.DeserializeObject<Rootobject>(s);
Console.ReadLine();
}
}


public class Rootobject
{
public string type { get; set; }
public string Name { get; set; }
public string Language { get; set; }
public Actors Actors { get; set; }
}

public class Actors
{
public string type { get; set; }
public Values[] values { get; set; }
}

public class Values
{
public string type { get; set; }
public string Name { get; set; }
}

}

我能做些什么吗,或者我应该尝试找到原始类?

更新

我不关心“$type”属性。它甚至不在原始模型上。我只想将 JSON 反序列化为强类型模型,包括集合(我的真实类有更多嵌套级别),但自动生成的类型(使用 Paste Json)不起作用。

最佳答案

如果您只想忽略类型信息,那么:

  • 如果您使用 TypeNameHandling.None 进行反序列化,那么对象 上的 "$type" 属性将被简单地忽略,不会在反序列化过程中造成任何问题。

  • 但即使使用 TypeNameHandling.None集合值"$type" 属性也会导致问题,因为为集合生成的类型元数据包含强制在 JSON 中嵌套的额外级别:

    使用 "type" :

    {
    "Actors": {
    "$type": "ConsoleAppCompare.Character[], ConsoleAppCompare",
    "$values": []
    }
    }

    没有:

    {
    "Actors": []
    }

    使用 TypeNameHandling.None 反序列化 JSON 时,如果遇到具有额外嵌套级别的序列化集合,则会抛出异常。

    所以你需要一些方法来在反序列化过程中去除额外的嵌套级别,例如与 custom JsonConverter 。在 this answer 问题 Strategies for migrating serialized Json.NET document between versions/formats 中,有一个已经编写并可供使用:IgnoreCollectionTypeConverter

因此您可以按如下方式定义您的模型:

public class Rootobject
{
public string Name { get; set; }
public string Language { get; set; }
public List<Actor> Actors { get; set; }
}

public class Actor
{
public string Name { get; set; }
}

反序列化如下:

var settings = new JsonSerializerSettings
{
Converters = { new IgnoreCollectionTypeConverter() },
};
var movie = JsonConvert.DeserializeObject<Rootobject>(s, settings);

示例 fiddle

注意事项:

更新

你问过,我只想将 json 反序列化为强类型模型,包括集合(我的真实类有更多嵌套级别),但自动生成的类型(使用 Paste Json)不起作用。

在您的开发过程中,您可以使用 LINQ to JSON 将您的 JSON 加载到内存中,删除所有 "$type" 元数据,并写入一个新的 JSON 字符串。然后,您可以获取已清理的字符串并将其用于“将 Json 粘贴为类”。

以下扩展方法将完成必要的工作:

public static class JsonExtensions
{
const string valuesName = "$values";
const string typeName = "$type";

public static JToken RemoveTypeMetadata(this JToken root)
{
if (root == null)
throw new ArgumentNullException();
var types = root.SelectTokens(".." + typeName).Select(v => (JProperty)v.Parent).ToList();
foreach (var typeProperty in types)
{
var parent = (JObject)typeProperty.Parent;
typeProperty.Remove();
var valueProperty = parent.Property(valuesName);
if (valueProperty != null && parent.Count == 1)
{
// Bubble the $values collection up removing the synthetic container object.
var value = valueProperty.Value;
if (parent == root)
{
root = value;
}
// Remove the $values property, detach the value, then replace it in the parent's parent.
valueProperty.Remove();
valueProperty.Value = null;
if (parent.Parent != null)
{
parent.Replace(value);
}
}
}
return root;
}
}

示例工作 .Net fiddle 接受您输入的 JSON 字符串并返回:

{
"Name": "Avengers",
"Language": "En",
"Actors": [
{
"Name": "Phil Coulson"
},
{
"Name": "Tony Stark"
}
]
}

关于c# - 反序列化使用 TypeNameHandling.All 序列化的字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47802385/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com