2015-01-24 3 views
4

Один из способов десериализации интерфейса и абстрактных свойств - это класс, устанавливающий TypeNameHandling в Auto во время сериализации и десериализации. Однако, когда я пытаюсь то же самое, когда сериализации и десериализации объекта интерфейса напрямую, он не работает -Сериализация интерфейса/абстрактного объекта с использованием NewtonSoft.JSON

interface ISample 
{ 
    string Key { get; set; } 
} 

class A : ISample 
{ 
    public string Key { get; set; } 

    public A(string key) 
    { 
     this.Key = key; 
    } 
} 

class B : ISample 
{ 
    public string Key { get; set; } 

    public B(string key) 
    { 
     this.Key = key; 
    } 
} 

сериализации и десериализации код -

ISample a = new A("keyA"); 
ISample b = new B("keyB"); 

var settings = new JsonSerializerSettings(); 
settings.TypeNameHandling = TypeNameHandling.Auto; 

var stringA = JsonConvert.SerializeObject(a, settings); 
var stringB = JsonConvert.SerializeObject(b, settings); 

Console.WriteLine(stringA); 
Console.WriteLine(stringB); 

a = JsonConvert.DeserializeObject<ISample>(stringA, settings); 
b = JsonConvert.DeserializeObject<ISample>(stringB, settings); 

Я заметил, что даже при установке TypeNameHandling.Auto информация типа отсутствует в сериализованной строке. Тем не менее, настройки TypeNameHandling для Object или All работают.

Я пропустил что-то основное здесь?

ответ

4

Чтобы включить вывод $type информации на корневом уровне для полиморфного объекта с TypeNameHandling.Auto, с помощью следующей перегрузки: JsonConvert.SerializeObject Method (Object, Type, JsonSerializerSettings). Из docs:

public static string SerializeObject(
    Object value, 
    Type type, 
    JsonSerializerSettings settings 
) 

Тип Тип: System.Type Тип значения сериализации. Этот параметр используется, когда TypeNameHandling является Auto, чтобы записать имя типа, если тип значения не совпадает. Указание типа является необязательным.

В вашем случае, вы могли бы сделать:

var stringA = JsonConvert.SerializeObject(a, typeof(ISample), settings); 
var stringB = JsonConvert.SerializeObject(b, typeof(ISample), settings); 

Console.WriteLine(stringA); 
Console.WriteLine(stringB); 

И получить результат:

{"$type":"Tile.TestJsonDotNet.A, Tile","Key":"keyA"} 
{"$type":"Tile.TestJsonDotNet.B, Tile","Key":"keyB"} 

ли принять к сведению этого предостережения от Newtonsoft docs:

TypeNameHandling следует использовать с осторожностью, когда ваше приложение десериализует JSON от внешний источник. Входящие типы должны быть проверены с помощью специального SerializationBinder при десериализации со значением, отличным от None.

Для обсуждения того, почему это может оказаться необходимым, см TypeNameHandling caution in Newtonsoft Json, How to configure Json.NET to create a vulnerable web API и BlackHat бумаги Альваро Муньос & Александра Mirosh в https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf

+0

Спасибо, что работал! – ambivi

Смежные вопросы