2015-10-30 6 views
2

У меня есть класс, который я использую для конфигурации, которая содержит 3 кортежа всех целых чисел.Проблемы десериализации Json с кортежами?

public class Configuration 
{ 
    public List<Tuple<int, int, int>> MyThreeTuple { get; set; } 

    public Configuration() 
    { 
     MyThreeTuple = new List<Tuple<int, int, int>>(); 
     MyThreeTuple.Add(new Tuple<int, int, int>(-100, 20, 501)); 
     MyThreeTuple.Add(new Tuple<int, int, int>(100, 20, 864)); 
     MyThreeTuple.Add(new Tuple<int, int, int>(500, 20, 1286)); 
    } 
} 

Этот класс сериализовать в Json с System.Web.Script.Serialization как таковой

JavaScriptSerializer jsonSerializer = new JavaScriptSerializer(); 
String configJson = jsonSerializer.Serialize(config); 
File.WriteAllText(configPath, configJson); 

, а затем десериализации при запуске приложения

String configJson = File.ReadAllText(configPath); 
JavaScriptSerializer jsonSerializer = new JavaScriptSerializer(); 
object jsonObject = jsonSerializer.Deserialize(configJson, typeof(ApplicationConfiguration)); 
appConfig = (Configuration)jsonObject; 

Моя проблема заключается в том, что всякий раз, когда я иду в десериализации JSon исключено исключение

System.MissingMethodException in System.Web.Extensions.dll 

С сообщением

No parameterless constructor defined for type of `System.Tuple`3 .... 

Это то, что производится Json для кортежа выглядит

"MyThreeTuple": 
[ 
    {"Item1":-100,"Item2":20,"Item3":501}, 
    {"Item1":100,"Item2":20,"Item3":864}, 
    {"Item1":500,"Item2":20,"Item3":1286} 
] 

Любая идея, как решить эту проблему?

EDIT:

Как другие предположили, я опробовал JSon.NET и, кажется, работает десериализации JSON. Хотя я нашел странную причуду.

Таким образом, конструктор для моего класса Configuration заполняет значения по умолчанию для конфигурации. В частности, что указано в коде выше. Я обнаружил, что могу сериализовать конфигурацию с разными значениями, но при десериализации значения по умолчанию также загружаются в List<Tuple<>>.

Я предполагаю, что Json.Net обошел проблему Tuple, не имея конструктора без параметров, сначала создавая экземпляр Configuration, а затем устанавливая его значения.

Кажется, что создается экземпляр класса, затем List.Add ing Tuple s он находит в json список. Вместо того, чтобы очищать список, добавляя то, что он находит.

Есть ли возможность в JSon.Net решить эту проблему?

+0

Systen.Tuple не делает имеют безпараметрический конструктор. – MajkeloDev

+0

http://stackoverflow.com/questions/13739348/why-i-could-not-serialize-a-tuple-in-c прочитать это Вопрос и ответы – MajkeloDev

+1

Если вы хотите использовать JSON.net, он [поддерживает Tuple сериализация] (http://stackoverflow.com/questions/16101115/how-does-a-tuple-serialize-to-and-deserialize-from-json). –

ответ

2

Причина, почему вы получили эту ошибку, потому что JavaScriptSerializer требует открытого параметр меньше конструктора, который не относится к кортежам, потому что это immutable

посмотри здесь http://json.codeplex.com/ для полного сравнения между JavaScriptSerializer и json.net

Даже майкрософт состояния в documentation

Json.NET следует использовать сериализации и десериализации. Обеспечивает функции сериализации и десериализации для приложений с поддержкой AJAX.

вот пример того, как вы можете легко использовать JsonConvert для достижения этой

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using Newtonsoft.Json; 

namespace ConsoleApplication25 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Configuration configuration = new Configuration(); 
      string configJson = JsonConvert.SerializeObject(configuration); 
      File.WriteAllText(configPath, configJson); 
      //Deserialize the content after you read your file in string 

      var configurationDeserialized = JsonConvert.DeserializeObject<Configuration>(configJson); 



     } 
    } 
} 

public class Configuration 
{ 
    [JsonIgnore] 
    public List<Tuple<int, int, int>> MyThreeTuple { get; set; } 

    public Configuration() 
    { 
     MyThreeTuple = new List<Tuple<int, int, int>>(); 
     MyThreeTuple.Add(new Tuple<int, int, int>(-100, 20, 501)); 
     MyThreeTuple.Add(new Tuple<int, int, int>(100, 20, 864)); 
     MyThreeTuple.Add(new Tuple<int, int, int>(500, 20, 1286)); 
    } 
} 
+0

Тестирование вашего примера не имеет смысла. Поскольку 'new Configuration()' уже добавляет три кортежа, ваш тест не может отличить «MyThreeTuple» от того, что он не сериализуется вообще, «MyThreeTuple» сериализуется, но игнорируется во время десериализации, а «MyThreeTuple» сериализуется и десериализован правильно. (Но даже если ваше тестирование неверно, результат все равно может быть.) – hvd

+0

@hvd у вас есть право, но исправлено с помощью простого [JsonIgnore] –

1

Вы можете решить с помощью Newtonsoft.Json

  1. Установка Newtonsoft.Json с помощью NuGet (https://www.nuget.org/packages/Newtonsoft.Json/)

Серийный номер:

var myObject = new Configuration(); 
var objString = JsonConvert.SerializeObject(myObject); 

Deserialize:

var result = JsonConvert.DeserializeObject(objString, typeof(Configuration)); 

Или

var result = JsonConvert.DeserializeObject<Configuration>(objString); 
0

Просто для полноты картины, я хотел бы отметить, что является можно десериализации Tuple<int, int, int> используя JavaScriptSerializer, но вам нужно JavaScriptConverter сделать это. Конвертер обрабатывает экземпляр Tuple из значений в JSON, тем самым избегая исключения.

class ThreeTupleConverter : JavaScriptConverter 
{ 
    public override IEnumerable<Type> SupportedTypes 
    { 
     get { return new List<Type> { typeof(Tuple<int, int, int>) }; } 
    } 

    public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer) 
    { 
     int item1 = (int)dictionary["Item1"]; 
     int item2 = (int)dictionary["Item2"]; 
     int item3 = (int)dictionary["Item3"]; 
     return new Tuple<int, int, int>(item1, item2, item3); 
    } 

    public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer) 
    { 
     throw new NotImplementedException(); 
    } 
} 

Чтобы использовать конвертер, вы должны зарегистрировать его сериализатором как это:

var serializer = new JavaScriptSerializer(); 
serializer.RegisterConverters(new List<JavaScriptConverter> { new ThreeTupleConverter() }); 

Тогда десериализации, как обычно, и он должен работать нормально:

string configJson = @" 
{ 
    ""MyThreeTuple"": 
    [ 
     { ""Item1"": -100, ""Item2"": 20, ""Item3"": 501 }, 
     { ""Item1"": 100, ""Item2"": 20, ""Item3"": 864 }, 
     { ""Item1"": 500, ""Item2"": 20, ""Item3"": 1286 } 
    ] 
}"; 

var config = serializer.Deserialize<Configuration>(configJson); 

foreach (var tuple in config.MyThreeTuple) 
{ 
    Console.WriteLine("(" + tuple.Item1 + ", " + tuple.Item2 + ", " + tuple.Item3 + ")"); 
} 

Выход :

(-100, 20, 501) 
(100, 20, 864) 
(500, 20, 1286) 
Смежные вопросы