19

JsonConverter読み取り/書き込みで達成する必要があるいくつかの変換タスクを実行するために を書いています。特に、既存のシリアライゼーション動作を採用し、書き込み時にいくつかの追加プロパティに取り組み、読み取り時にそれらの追加プロパティを読み取ります。

の内部では、渡されたインスタンスを利用して、変換機能の大部分を実行しJsonConverterたいと考えています。JsonSerializerただし、これを行うと、シリアライザーがコンバーターを呼び出し、コンバーターを呼び出すシリアライザーなどを呼び出す再帰ループに陥ります。

を除くJsonConvert.SerializeObjectすべてのコンバーターをシリアライザー インスタンスから渡し、use などのことを行う人を見てきました。ただし、カスタム コントラクト リゾルバーや処理など、シリアライザーで行った他のすべてのカスタマイズがバイパスされるため、これはうまくいきません。 thisDateTime

私ができる方法はありますか:

  1. 渡されたシリアライザーのインスタンスを使用しますが、何らかの方法でコンバーターを除外するか、または
  2. 渡されたシリアライザーを複製し (手動で新しいシリアライザーを作成してプロパティごとにコピーせずに)、コンバーターを削除しますか?
4

3 に答える 3

6

これは非常に一般的な問題です。「JsonConvert.SerializeObject」を使用することは悪い考えではありません。ただし、一部の状況 (通常はコレクション) で使用できる 1 つのトリックは、書き込み時にインターフェイスにキャストし、読み取り時に単純な派生物に逆シリアル化することです。

以下は、オブジェクトのように見えるのではなく、KVP のセットとしてシリアル化された可能性のある辞書を処理する単純なコンバーターです (ここで私の年齢を示しています:))

「WriteJson」は IDictionary< K,V> にキャストし、「ReadJson」は「DummyDictionary」を使用することに注意してください。最終的には正しい結果になりますが、再帰を引き起こすことなく、渡されたシリアライザーを使用します。

/// <summary>
/// Converts a <see cref="KeyValuePair{TKey,TValue}"/> to and from JSON.
/// </summary>
public class DictionaryAsKVPConverter<TKey, TValue> : JsonConverter
{
    /// <summary>
    /// Determines whether this instance can convert the specified object type.
    /// </summary>
    /// <param name="objectType">Type of the object.</param>
    /// <returns>
    ///     <c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
    /// </returns>
    public override bool CanConvert(Type objectType)
    {
        if (!objectType.IsValueType && objectType.IsGenericType)
            return (objectType.GetGenericTypeDefinition() == typeof(Dictionary<,>));

        return false;
    }

    /// <summary>
    /// Writes the JSON representation of the object.
    /// </summary>
    /// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
    /// <param name="value">The value.</param>
    /// <param name="serializer">The calling serializer.</param>
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var dictionary = value as IDictionary<TKey, TValue>;
        serializer.Serialize(writer, dictionary);
    }

    /// <summary>
    /// Reads the JSON representation of the object.
    /// </summary>
    /// <param name="reader">The <see cref="JsonReader"/> to read from.</param>
    /// <param name="objectType">Type of the object.</param>
    /// <param name="existingValue">The existing value of object being read.</param>
    /// <param name="serializer">The calling serializer.</param>
    /// <returns>The object value.</returns>
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        Dictionary<TKey, TValue> dictionary;

        if (reader.TokenType == JsonToken.StartArray)
        {
            dictionary = new Dictionary<TKey, TValue>();
            reader.Read();
            while (reader.TokenType == JsonToken.StartObject)
            {
                var kvp = serializer.Deserialize<KeyValuePair<TKey, TValue>>(reader);
                dictionary[kvp.Key] = kvp.Value;
                reader.Read();
            }
        }
        else if (reader.TokenType == JsonToken.StartObject)
            // Use DummyDictionary to fool JsonSerializer into not using this converter recursively
            dictionary = serializer.Deserialize<DummyDictionary>(reader);
        else
            dictionary = new Dictionary<TKey, TValue>();

        return dictionary;
    }

    /// <summary>
    /// Dummy to fool JsonSerializer into not using this converter recursively
    /// </summary>
    private class DummyDictionary : Dictionary<TKey, TValue> { }
}
于 2016-03-20T16:38:04.687 に答える
-8

申し訳ありませんが、混乱しているかもしれません。オブジェクトをシリアル化するためにこのメソッドを使用しました。

using System;
using Newtonsoft.Json;

namespace Utilities
{
    public static class serializer
    {
        public static string SerializeObject(object objectModel) {
            return JsonConvert.SerializeObject(objectModel);
        }
        public static object DeserializeObject<T>(string jsonObject)
        {
            try
            {
                return JsonConvert.DeserializeObject<T>(jsonObject);
            }
            catch (Exception ex) { return null; }
            
        }
    }
}

そして、私はこのコードを使用しました:

userLoged = (modelUser)serializer.DeserializeObject<modelUser>((string)Session["userLoged"]);

これがお役に立てば幸いです。

于 2016-04-27T21:38:36.013 に答える