JavaScriptSerializer. Десериализуйте - как изменить имена полей

Я был долгим временем пользователь Accurev и недавно переместился в задание, где я использую По необходимости. Я должен сказать Вам, мне жаль, что у меня не было Accurev назад. Я действительно соглашаюсь - UI является медленным и имеет проблемы.

Однако там существуют некоторые ДЕЙСТВИТЕЛЬНО ПОТРЯСАЮЩИЕ инструменты визуализации. Я не могу полагать, что любой посмотрел бы на браузер истории версий и не влюбился бы! Потоковый браузер является большим простым инструментом для понимания то, что продолжается в организации разработки.

кроме того, грязь, простая администрировать. Accurev является на самом деле одним из моих любимых инструментов.

72
задан 6 revs 10 July 2009 в 13:45
поделиться

4 ответа

I took another try at it, using the DataContractJsonSerializer class. This solves it:

The code looks like this:

using System.Runtime.Serialization;

[DataContract]
public class DataObject
{
    [DataMember(Name = "user_id")]
    public int UserId { get; set; }

    [DataMember(Name = "detail_level")]
    public string DetailLevel { get; set; }
}

And the test is:

using System.Runtime.Serialization.Json;

[TestMethod]
public void DataObjectSimpleParseTest()
{
        DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(DataObject));

        MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(JsonData));
        DataObject dataObject = serializer.ReadObject(ms) as DataObject;

        Assert.IsNotNull(dataObject);
        Assert.AreEqual("low", dataObject.DetailLevel);
        Assert.AreEqual(1234, dataObject.UserId);
}

The only drawback is that I had to change DetailLevel from an enum to a string - if you keep the enum type in place, the DataContractJsonSerializer expects to read a numeric value and fails. See DataContractJsonSerializer and Enums for further details.

In my opinion this is quite poor, especially as JavaScriptSerializer handles it correctly. This is the exception that you get trying to parse a string into an enum:

System.Runtime.Serialization.SerializationException: There was an error deserializing the object of type DataObject. The value 'low' cannot be parsed as the type 'Int64'. --->
System.Xml.XmlException: The value 'low' cannot be parsed as the type 'Int64'. --->  
System.FormatException: Input string was not in a correct format

And marking up the enum like this does not change this behaviour:

[DataContract]
public enum DetailLevel
{
    [EnumMember(Value = "low")]
    Low,
   ...
 }

This also seems to work in Silverlight.

72
ответ дан 24 November 2019 в 12:41
поделиться

Json.NET will do what you want (disclaimer: I'm the author of the package). It supports reading DataContract/DataMember attributes as well as its own to change the property names. Also there is the StringEnumConverter class for serializing enum values as the name rather than the number.

13
ответ дан 24 November 2019 в 12:41
поделиться

Создайте класс, унаследованный от JavaScriptConverter. Затем вы должны реализовать три вещи:

Методы-

  1. Сериализовать
  2. Десериализовать

Свойство-

  1. SupportedTypes

Вы можете использовать класс JavaScriptConverter, когда вам нужно больше контроля над процессом сериализации и десериализации.

JavaScriptSerializer serializer = new JavaScriptSerializer();
serializer.RegisterConverters(new JavaScriptConverter[] { new MyCustomConverter() });

DataObject dataObject = serializer.Deserialize<DataObject>(JsonData);

Вот ссылка для получения дополнительной информации

5
ответ дан 24 November 2019 в 12:41
поделиться

Создавая пользовательский JavaScriptConverter, вы можете сопоставить любое имя с любым свойством. Но для этого требуется ручное кодирование карты, что менее чем идеально.

public class DataObjectJavaScriptConverter : JavaScriptConverter
{
    private static readonly Type[] _supportedTypes = new[]
    {
        typeof( DataObject )
    };

    public override IEnumerable<Type> SupportedTypes 
    { 
        get { return _supportedTypes; } 
    }

    public override object Deserialize( IDictionary<string, object> dictionary, 
                                        Type type, 
                                        JavaScriptSerializer serializer )
    {
        if( type == typeof( DataObject ) )
        {
            var obj = new DataObject();
            if( dictionary.ContainsKey( "user_id" ) )
                obj.UserId = serializer.ConvertToType<int>( 
                                           dictionary["user_id"] );
            if( dictionary.ContainsKey( "detail_level" ) )
                obj.DetailLevel = serializer.ConvertToType<DetailLevel>(
                                           dictionary["detail_level"] );

            return obj;
        }

        return null;
    }

    public override IDictionary<string, object> Serialize( 
            object obj, 
            JavaScriptSerializer serializer )
    {
        var dataObj = obj as DataObject;
        if( dataObj != null )
        {
            return new Dictionary<string,object>
            {
                {"user_id", dataObj.UserId },
                {"detail_level", dataObj.DetailLevel }
            }
        }
        return new Dictionary<string, object>();
    }
}

Тогда вы можете десериализовать так:

var serializer = new JavaScriptSerializer();
serialzer.RegisterConverters( new[]{ new DataObjectJavaScriptConverter() } );
var dataObj = serializer.Deserialize<DataObject>( json );
20
ответ дан 24 November 2019 в 12:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: