Могу ли я десериализовать в неизменяемый объект, используя JavascriptSerializer? - PullRequest
4 голосов
/ 02 ноября 2010

с использованием System.Web.Script.Serialization.JavaScriptSerializer

можно ли как-нибудь десериализовать в неизменный объект?

   public class Item
{
    public Uri ImageUri { get;private set; }
    public string Name { get; private set; }
    public Uri ItemPage { get;private set; }
    public decimal Retail { get;private set; }
    public int? Stock { get; private set; }
    public decimal Price { get; private set; }


    public Item(Uri imageUri, string name, Uri itemPage, decimal retail, int? stock, decimal price)
    {
        ImageUri = imageUri;
        Name = name;
        ItemPage = itemPage;
        Retail = retail;
        Stock = stock;
        Price = price;
    }
}

Ограничения: я не хочу публичного пустого конструктора, я не хочу менять все на изменяемые, и я не хочу использовать xml вместо Json.

Ответы [ 2 ]

7 голосов
/ 12 декабря 2012

Мне нужно было найти ответ на этот вопрос, и, поскольку это первый результат в Google, но он не дал примера, я решил поделиться тем, что придумал (основываясь на ссылке, предоставленной Джеймсом Эллисом. Джонс.)

В моей ситуации мне нужен был объект "Деньги", чтобы быть неизменным. Моему объекту Money требовались сумма и валюта. Должен быть неизменным, потому что я использую его, как если бы это было десятичное значение, которое я заменяю (математические операции поддерживаются со значениями в аналогичной валюте), и мне нужно было передать его, не беспокоясь о том, передаю ли я по ссылке или копия вещи.

Итак, я реализовал JavaScriptConverter здесь:

public class MoneyJsonConverter : JavaScriptConverter
{

    public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
    {
        if (dictionary == null)
            throw new ArgumentNullException("dictionary");

        if (type != typeof(Money))
            return null;

        var amount = Convert.ToDecimal(dictionary.TryGet("Amount"));
        var currency = (string)dictionary.TryGet("Currency");

        return new Money(currency, amount);
    }

    public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
    {
        var moneyAmount = obj as Money;
        if (moneyAmount == null)
            return new Dictionary<string, object>();

        var result = new Dictionary<string, object>
            {
                { "Amount", moneyAmount.Amount },
                { "Currency", moneyAmount.Currency },
            };
        return result;
    }

    public override IEnumerable<Type> SupportedTypes
    {
        get { return new ReadOnlyCollection<Type>(new List<Type>(new[] { typeof(Money) })); }
    }
}

Затем я зарегистрировал конвертер с помощью JavaScriptSerializer через файл web.config:

<system.web.extensions>
    <scripting>
        <webServices>
            <jsonSerialization>
                <converters>
                    <add name="MoneyConverter" type="My.Namespace.MoneyJsonConverter, MyAssembly, Version=1.0.0.0, Culture=neutral"/>
                </converters>
            </jsonSerialization>
        </webServices>
    </scripting>
</system.web.extensions>

Вот и все! Я также украсил свой класс парой атрибутов, хотя:

[Serializable]
[Immutable]
public class Money
0 голосов
/ 29 сентября 2011

JavaScriptSerializer предоставляет API настройки, вы можете создать класс, который наследуется от JavaScriptConverter, чтобы указать, как создать класс Item из словаря, а затем использовать метод RegisterConverters на экземпляре JavaScriptSerializer для регистрации вашего пользовательского конвертера.

определение javascriptserializer.registerconverters

...