Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JSON.NET TypeNameHandling.Auto except for top level [duplicate]

Tags:

c#

json.net

Given the following snippet:

using System;
using Newtonsoft.Json;

namespace JsonTestje
{
    class Other
    {
        public string Message2 { get; set; }
    }

    class Demo
    {
        public string Message { get; set; }
        public Other Other { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var demo = new Demo
            {
                Message = "Hello, World!",
                Other = new Other
                {
                    Message2 = "Here be dragons!"
                }
            };

            var settings = new JsonSerializerSettings
            {
                TypeNameHandling = TypeNameHandling.Auto,
                Formatting = Formatting.Indented
            };
            var serialized = JsonConvert.SerializeObject(demo, settings);
            Console.WriteLine(serialized);
        }
    }
}

The output is this:

{
  "Message": "Hello, World!",
  "Other": {
    "Message2": "Here be dragons!"
  }
}

Now if I change TypeNameHandling to TypeNameHandling.All, the output becomes this:

{
  "$type": "JsonTestje.Demo, JsonTestje",
  "Message": "Hello, World!",
  "Other": {
    "$type": "JsonTestje.Other, JsonTestje",
    "Message2": "Here be dragons!"
  }
}

But what I want is this:

{
  "$type": "JsonTestje.Demo, JsonTestje",
  "Message": "Hello, World!",
  "Other": {
    "Message2": "Here be dragons!"
  }
}

The reason is that I want to be able to serialize a bunch of objects and deserialize them later, without knowing the type that they deserialize to, but I also don't want to pollute the content with these $type properties all over the place where they're not needed.

In other words, I want TypeNameHandling.Auto except for the root object. How do I do this?

like image 660
Dave Van den Eynde Avatar asked Oct 27 '15 11:10

Dave Van den Eynde


1 Answers

Well I figured it out by examining the source.

There's an overload that allows you to specify the 'root type' that you're passing. If the serializer finds that the type you passed is not the same (by being a descendant) it will write out the type name. The key is to specify System.Object as your root type, like this:

var serialized = JsonConvert.SerializeObject(demo, typeof(object), settings);
like image 170
Dave Van den Eynde Avatar answered Oct 26 '22 18:10

Dave Van den Eynde