与typenamehandling.laster.laster.laster.laster.sneperling.ly.



使用以下样本

序列化了类
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:UsersnvovoDesktopasdfaa.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; }
    }
}

我可以对此做任何事情,还是应该尝试找到原始类?

update

我不在乎" $ type"属性。它甚至不是原始型号。我只想将JSON的重新序列化为强烈键入的模型,包括收集(我的真实类具有更多的嵌套级别),但是自动生成的类型(使用粘贴JSON)不起作用。

如果您要做的就是 ignore 类型信息,则:

  • 如果您对TypeNameHandling.None进行了验证,则简单地忽略对象上的 "$type"属性将在避免时不会引起任何问题。

  • ,但即使使用 TypeNameHandling.None收集值的 "$type"属性引起问题,因为为收集生成的类型元数据包含JSON中的额外嵌套水平:

    使用"type"

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

    没有:

    {
      "Actors": []
    }
    

    当使用TypeNameHandling.None进行测试时,如果遇到了具有额外嵌套级别的序列化集合,则会抛出一个例外。

    因此,您需要某种方法来剥离避难化期间的额外嵌套水平,例如使用自定义JsonConverter。在此答案中,在版本/格式之间迁移序列化JSON.NET文档的问题策略中,已经写了一个并且可以使用: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);

样品小提琴。

注意:

  • IgnoreCollectionTypeConverter旨在与读/写作集合一起工作,这就是为什么我将 Actors从数组更改为 List<T>

  • 如果您需要 Process 类型信息而不是忽略它,则需要创建一个自定义ISerializationBinder。有关详细信息,请参见自定义序列化Binder。如何为二进制格式化器创建一个序列化的问题,该二进制格式化处理处理类型从一个组件和名称空间到另一个命名空间的移动提供了一种创建定制序列化粘合剂的解决方案。

update

您问,我只想将JSON验证为一个强烈键入的模型,包括收集(我的真实类具有更多的嵌套级别),但是自动生成的类型(使用粘贴JSON)不起作用。<<<<<<<<<<<<<<<<

在开发过程中,您可以使用LINQ将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小提琴,该小提琴带有您的输入JSON字符串并返回:

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

相关内容

  • 没有找到相关文章

最新更新