【问题标题】:Is there a better way to handle Encoding values with Json.Net?有没有更好的方法来使用 Json.Net 处理编码值?
【发布时间】:2013-05-27 19:50:31
【问题描述】:

我正在使用 Json.Net 对具有 System.Text.Encoding 类型的属性的类进行序列化/反序列化。尝试一个简单的测试,我的课程没有任何问题被序列化:

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 肯定有更好、更少涉及的方法吗?

【问题讨论】:

    标签: c# json json.net


    【解决方案1】:

    使用[DataContract][DataMember] 属性明确设置哪些属性将在您的TestClass 对象上进行序列化。

    1. 从您的TheEncoding 属性中省略[DataMember] 属性。
    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 将被序列化。

    【讨论】:

    • 显然我不仅是 Json.Net 的新手,而且是一般的 .Net 序列化。谢谢,成功了!
    【解决方案2】:

    我认为解决这个问题的更好方法是准确地确定您的 JSON 对象需要哪些属性?

    服务器端没有理由包含来自 Encoding 对象的所有属性,因为作为 .NET 框架的一部分,您已经可以在运行时访问它。

    在客户端上,我无法想象您为什么需要 Encoding 对象的所有属性。

    只发送EncodingNameBodyName 可能更直观,您可以从中确定要在服务器上使用的编码对象。

    例如,如果我要发送一些 JSON 到指定 utf-8 的服务器,我会知道使用 Encoding.UTF8

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-01-01
      • 1970-01-01
      • 2023-03-28
      • 1970-01-01
      • 2012-02-01
      • 2013-11-09
      • 1970-01-01
      相关资源
      最近更新 更多