Deserialize a string that has been serialized using TypeNameHandling.All

The class was serialized using the following example.

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

The above example creates the following 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"
      }
    ]
  }
}

Now, in another program that does not have access to the above models,
I have to deserialize the string for the object, but nothing I tried seems to work ...

To create my new models, I copied json to my clipboard and used the Visual Studio "Paste Special" functionality

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

}

Can I do something about this, or should I try to find the source classes?

Update

$type. . JSON , ( ), ( Paste Json) .

+2
1

, , , :

  • deserialize TypeNameHandling.None, "$type" , .

  • TypeNameHandling.None, "$type" , , , JSON:

    "type":

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

    :

    {
      "Actors": []
    }
    

    JSON TypeNameHandling.None, , .

    , - , . custom 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);

fiddle.

:

, json , ( ), ( Paste Json) .

LINQ to JSON JSON , "$type" JSON. "Paste Json as Classes".

:

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 parent.
                valueProperty.Remove();
                valueProperty.Value = null;
                if (parent.Parent != null)
                {
                    parent.Replace(value);
                }
            }
        }
        return root;
    }
}

. , JSON :

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

Source: https://habr.com/ru/post/1691902/


All Articles