Is there a better way to handle Encoding values with Json.Net?

一世执手 提交于 2019-12-24 02:26:14

问题


I am serializing/deserializing a class that has a property of type System.Text.Encoding with Json.Net. Trying out a simple test, my class serialized without any issue:

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 );

Serializes to:

{
  "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
  }
}

However, when deserializing, I got an exception:

Could not create an instance of type System.Text.Encoding. Type is an interface or abstract class and cannot be instantiated. Path 'TheEncoding.BodyName', line 3, position 16.

I was able to get past this issue by creating a custom converter that handles the System.Text.Encoding type:

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() );

Serializing with the custom converter now produces:

{
  "TheEncoding": "utf-8"
}

And this JSON can be successfully round-tripped back to the original object when deserialized with the custom converter.

I'm new to Json.Net, and I have a strong feeling that I'm doing this the hard way! Surely there is a better and less involved way to handle System.Text.Encoding?


回答1:


Use [DataContract] and [DataMember] attributes to explicity set which properties will be serialized on your TestClass objects.

  1. Omit the [DataMember] attribute from your TheEncoding property.
  2. Create a helper property which gets serialized as "utf-8" (depending on the value of TheEncoding). Include the [DataMember] attribute on this property.

For example:

[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
    }
  }
}

When serialized, TheEncoding will be skipped and TheEncodingName will be serialized instead.




回答2:


I think the better way to approach this problem is to figure out exactly what properties do you need on your JSON object?

Server side there's no reason to include all of the properties from the Encoding object because you already have access to it at run time as part of the .NET framework.

On the client I can't imagine why you would need all of the properties from the Encoding object.

It might be more intuitive to just send the EncodingName or BodyName and from that you can determine what encoding object to use on the server.

As an example, if I were to send some JSON to the server specifying utf-8 I would know to use Encoding.UTF8.



来源:https://stackoverflow.com/questions/16866632/is-there-a-better-way-to-handle-encoding-values-with-json-net

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!