9

私が取り組んでいるプロジェクトでは、Json.Net ライブラリの使用を開始しました。

ただし、json.net が文字列型で「緩い」ことがわかりました。

次に例を示します。

DTO クラス

[JsonObject]
public class DTO
{
    [JsonProperty]
    public string type;
}

デシリアライゼーション

byte[] rawBody = GetBytes(@"{""type"":true}");
using (MemoryStream ms = new MemoryStream(rawBody))
{
    using (StreamReader sr = new StreamReader(ms))
    {
        var serializer = new JsonSerializer();

        return serializer.Deserialize(sr, typeof(DTO));
     }
 }

これにより、「type」属性が「True」として逆シリアル化されます。ただし、型の不一致があるため、失敗して例外がスローされると予想されます。json で true を 1 に置き換えても同じです。プロパティ「タイプ」の値は「1」になります。

質問:

  1. 厳密なシリアル化を強制する方法はありますか?

  2. ここで見られるような暗黙的な変換を持つ文字列以外の型はありますか?

ありがとうございました。

JF

4

2 に答える 2

3

私は回避策を思いついた。

それは機能しますが、それが私の「問題」を解決する良い方法であるかどうかはわかりません。

から変換するためにコンバーターを使用しました

これが私がしたことです:

[JsonObject]
public class DTO
{
    [JsonProperty]
    public string type;
}

カスタムコンバーター:

class JsonStrictConverter<T> : JsonConverter
    {
        public JsonToken[] TokenTypes { get; set; }

        public JsonStrictConverter(params JsonToken[] tokenTypes)
        {
            TokenTypes = tokenTypes;
        }

        public override bool CanConvert(Type objectType)
        {
            return objectType == typeof(T);
        }
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            if (reader.TokenType == JsonToken.Null)
            {
                if (objectType.IsValueType)
                {
                    return Activator.CreateInstance(objectType);
                }
                return null;
            }

            var converter = System.ComponentModel.TypeDescriptor.GetConverter(typeof(T));
            return (T)converter.ConvertFromString(reader.Value.ToString());
        }
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            throw new NotImplementedException("The converter '" + this.GetType().Name + "' is not intended to be used when serializing.");
        }
        public override bool CanWrite { get { return false; } }
    }

デシリアライズ:

XmlDictionaryReader bodyReader = message.GetReaderAtBodyContents();
bodyReader.ReadStartElement("Binary");
byte[] rawBody = bodyReader.ReadContentAsBase64();
using (MemoryStream ms = new MemoryStream(rawBody))
{
    using (StreamReader sr = new StreamReader(ms))
    {
        var serializer = new JsonSerializer();
        /* These converter are present to enforce strict data type in the json. */ 
        /* by default, newtonsoft can serialize Numbers as strings, strings as boolean, etc.... */
        serializer.Converters.Add(new JsonStrictConverter<string>(JsonToken.String));
        serializer.Converters.Add(new JsonStrictConverter<bool>(JsonToken.Boolean));
        serializer.Converters.Add(new JsonStrictConverter<short>(JsonToken.Integer));
        serializer.Converters.Add(new JsonStrictConverter<ushort>(JsonToken.Integer));
        serializer.Converters.Add(new JsonStrictConverter<int>(JsonToken.Integer));
        serializer.Converters.Add(new JsonStrictConverter<uint>(JsonToken.Integer));
        serializer.Converters.Add(new JsonStrictConverter<long>(JsonToken.Integer));
        serializer.Converters.Add(new JsonStrictConverter<ulong>(JsonToken.Integer));
        serializer.Converters.Add(new JsonStrictConverter<float>(JsonToken.Float, JsonToken.Integer));
        serializer.Converters.Add(new JsonStrictConverter<double>(JsonToken.Float, JsonToken.Integer));
        serializer.Converters.Add(new JsonStrictConverter<decimal>(JsonToken.Float, JsonToken.Integer));

        return serializer.Deserialize(sr, typeof(DTO));                    
    }
}

このアプローチに欠けているタイプはありますか?

周りの誰かがより良い解決策を持っていますか?

ありがとうございました。

于 2012-11-07T19:25:22.197 に答える
0

json.netは厳密な型のシリアル化を処理し、さらに.netjsonシリアライザーよりもはるかに高速であると考えてください。 http://json.codeplex.com

于 2012-11-09T13:48:14.620 に答える