2013-05-31 3 views
2

Я сериализую/десериализую класс, который имеет свойство типа System.Text.Encoding с Json.Net. Пробуя простой тест, мой класс сериализовать без выпуска:Есть ли лучший способ обрабатывать значения кодировки с помощью Json.Net?

public class TestClass { 
    public Encoding TheEncoding { get; set; } 
} 

var testClass = new TestClass { TheEncoding = Encoding.UTF8 }; 
var json = JsonConvert.SerializeObject(testClass, Formatting.Indented); 
var obj = JsonConvert.DeserializeObject<TestClass>(json); 

Сериализует к:

{ 
    "TheEncoding": { 
    "BodyName": "utf-8", 
    "EncodingName": "Unicode (UTF-8)", 
    "HeaderName": "utf-8", 
    "WebName": "utf-8", 
    "WindowsCodePage": 1200, 
    "IsBrowserDisplay": true, 
    "IsBrowserSave": true, 
    "IsMailNewsDisplay": true, 
    "IsMailNewsSave": true, 
    "IsSingleByte": false, 
    "EncoderFallback": { 
     "DefaultString": "?", 
     "MaxCharCount": 1 
    }, 
    "DecoderFallback": { 
     "DefaultString": "?", 
     "MaxCharCount": 1 
    }, 
    "IsReadOnly": true, 
    "CodePage": 65001 
    } 
} 

Однако, когда десериализации, я получил исключение:

Не удалось создать экземпляр типа System.Text.Encoding. Тип является интерфейсом или абстрактным классом и не может быть создан. Путь 'TheEncoding.BodyName', строка 3, позиция 16.

я смог пройти эту проблему, создав пользовательский конвертер, который обрабатывает тип System.Text.Encoding:

public class JsonEncodingConverter : JsonConverter { 
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { 
     // Serialize as the BodyName. 
     serializer.Serialize(writer, (value as Encoding).BodyName); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { 
     // Already good to go. 
     return existingValue; 
    } 

    public override bool CanConvert(Type objectType) { 
     return (typeof (Encoding).IsAssignableFrom(objectType)); 
    } 
} 

var testClass = new TestClass { TheEncoding = Encoding.UTF8 }; 
var json = JsonConvert.SerializeObject(testClass, Formatting.Indented, new JsonEncodingConverter()); 
var obj = JsonConvert.DeserializeObject<TestClass>(json , new JsonEncodingConverter()); 

Сериализация с пользовательским конвертером теперь производит:

{ 
    "TheEncoding": "utf-8" 
} 

И это JSON может быть успешно круглодонным споткнулись назад к исходному объекту при десериализации с настраиваемым преобразователем.

Я новичок в Json.Net, и у меня есть сильное чувство, что я делаю это с трудом! Разумеется, есть лучший и менее привлекательный способ обработки System.Text.Encoding?

ответ

2

Используйте [DataContract] и [DataMember] атрибуты для набора эксплицитов, свойства которого будут сериализованы на ваших объектах TestClass.

  1. Опустите атрибут [DataMember] от вашего TheEncoding.
  2. Создайте вспомогательное свойство, которое сериализуется как «utf-8» (в зависимости от значения TheEncoding). Включите в это свойство атрибут [DataMember].

Например:

[DataContract] 
public class TestClass 
{ 
    public Encoding TheEncoding { get; set; } 

    [DataMember] 
    public string TheEncodingName 
    { 
    get 
    { 
     if (this.TheEncoding == System.Text.Encoding.UTF8) 
     return "utf-8"; 
     // TODO: More possibilities 
    } 
    set 
    { 
     if (value == "utf-8") 
     this.TheEncoding = System.Text.Encoding.UTF8; 
     // TODO: More possibilities 
    } 
    } 
} 

При сериализации, TheEncoding будет пропущен и TheEncodingName будет сериализовать вместо этого.

+0

Очевидно, что я не только знаком с Json.Net, но и сериализацией .Net в целом. Спасибо, это помогло! – Darryl

0

Я думаю, что лучший способ подойти к этой проблеме - выяснить, какие именно свойства вам нужны на вашем объекте JSON?

На стороне сервера нет причин включать все свойства из объекта Encoding, поскольку у вас уже есть доступ к нему во время выполнения в рамках платформы .NET.

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

Возможно, было бы более интуитивно просто отправить EncodingName или BodyName и из этого вы можете определить, какой объект кодирования использовать на сервере.

В качестве примера, если бы я отправил некоторый JSON на сервер, указав utf-8 Я бы знал, что вы используете Encoding.UTF8.

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