Какой сериализатор JSON для .NET будет вставлять элементы в список, а не заменять список? - PullRequest
1 голос
/ 03 мая 2011

Хорошо, у меня есть базовая настройка класса ...

public class Location
{
    public string Name{ get; set; }

    private LocationList _LocationList = new LocationList();   
    public LocationList Locations{ get{ return _LocationList; } }
}

public class LocationList : List<Location>{}

public class ViewModel
{
    private LocationList _LocationList = new LocationList();   
    public LocationList Locations{ get{ return _LocationList; } }
}

, которую я хочу использовать с сериализатором JSON Newtonsoft.Однако сериализатор не вставляет элементы в существующую коллекцию за средством доступа к свойствам, доступным только для чтения, а скорее пытается присвоить свойству совершенно новый List, что, конечно же, невозможно, поскольку в нем нет установщика.

Теперь я мог бы просто переключиться на это ...

public class Location
{
    public string Name{ get; set; }
    public LocationList Locations{ get; set; }
}

public class LocationList : List<Location>{}

public class ViewModel
{
    public LocationList RootLocations{ get; set; }
}

Но теперь свойство списка не доступно только для чтения и может быть установлено на ноль.Даже если мы сделаем установщик закрытым, десериализация JSON все равно может установить его на ноль.

Мне нужен способ сказать сериализатору: «Возьмите элементы, которые есть в вашем списке, и вставьте их в этот уже существующий».list "вместо того, чтобы говорить" Замените мой список вашим полностью ".

Так можно ли это сделать, или мне придется написать свой собственный преобразователь сериализации JSON и подключить его?

M

1 Ответ

0 голосов
/ 03 мая 2011

Я не знаю о JSON.NET, но если вы используете JavaScriptSerializer, вы можете предоставить собственный сериализатор, но все равно использовать встроенный синтаксический анализ / форматирование и т. Д .:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Web.Script.Serialization;


class Program
{
    static void Main(string[] args)
    {

        JavaScriptSerializer ser = new JavaScriptSerializer();
        ser.RegisterConverters(new[] { new ViewModelConverter() });

        var model = new ViewModel { Locations = { new Location { Name = "abc",
            Locations = { new Location { Name = "def"}}} } };
        var json = ser.Serialize(model);

        var clone = (ViewModel)ser.Deserialize(json, typeof(ViewModel));
    }

}

public class ViewModelConverter : JavaScriptConverter
{

    public override IEnumerable<Type> SupportedTypes
    {
        get { return new[] { typeof(Location), typeof(ViewModel) }; }
    }
    public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
    {
        if (obj is ViewModel)
        {
            return new Dictionary<string, object> { { "locations", ((ViewModel)obj).Locations } };
        }
        if (obj is Location)
        {
            return new Dictionary<string, object> {
                {"name", ((Location)obj).Name},
                { "locations", ((Location)obj).Locations }
            };
        }
        throw new NotSupportedException();
    }
    public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
    {
        if (type == typeof(ViewModel))
        {
            var model = new ViewModel();
            ReadLocations(model.Locations, dictionary, serializer);
            return model;
        }
        if (type == typeof(Location))
        {
            var loc = new Location();
            if (dictionary.ContainsKey("name"))
            {
                loc.Name = (string)dictionary["name"];
            }
            ReadLocations(loc.Locations, dictionary, serializer);
            return loc;
        }
        throw new NotSupportedException();
    }
    static void ReadLocations(LocationList locations, IDictionary<string, object> dictionary, JavaScriptSerializer serializer)
    {
        if (dictionary.ContainsKey("locations"))
        {
            foreach (object item in (IList)dictionary["locations"])
            {
                locations.Add((Location)serializer.ConvertToType<Location>(item));
            }
        }
    }
}
public class Location
{
    public string Name { get; set; }

    private LocationList _LocationList = new LocationList();
    public LocationList Locations { get { return _LocationList; } }
}

public class LocationList : List<Location> { }

public class ViewModel
{
    private LocationList _LocationList = new LocationList();
    public LocationList Locations { get { return _LocationList; } }
}
...