1

私の問題は、コンバーターがインターフェースの実装に適用され、プロパティタイプがインターフェースである場合、JsonConverter が json.net デシリアライゼーション プロセスによって呼び出されないように見えることです。TypeNameHandling = TypeNameHandling.Objects を使用して、json に $type を追加します。シリアライゼーションとデシリアライゼーションの両方でそうします。また、インターフェイスの実装であるプロパティがある場合、クラスのコンバーターが適切に呼び出されます。しかし、インターフェイス型のプロパティがある場合、具象クラスのコンバーターは呼び出されません。

このクラスを逆シリアル化すると、JsonDataBagCreationConverter は RealTelephone によって呼び出されますが、これはインターフェイスであるため、Telephone では呼び出されません。どちらも正しい $type でシリアル化されていますが。これにより、RealTelephone の .Data が満たされ、Telephones .Data が null になります。

[JsonConverter(typeof(JsonDataBagCreationConverter<ContainerForITelephone>))]
public class ContainerForITelephone : IDataBag
{
    private object _data;
    private DataBagTypeEnum _dataBagTypeEnum;
    public ITelephone Telephone { get; set; }
    public Telephone RealTelephone { get; set; }

    public object Data
    {
        get { return _data; }
        set { _data = value; }
    }

    public DataBagTypeEnum DataBagType_Enum
    {
        get { return _dataBagTypeEnum; }
    }
}

この jsonconverter は Telephone プロパティに対して呼び出されません。ただし、これは RealTelephone 用です。

public class JsonDataBagCreationConverter<T> : JsonConverter where T : IDataBag, new()
{       
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {           
        if (reader.TokenType != JsonToken.Null) 
        {
            var jsonObject = JObject.Load(reader);
            var target = Create(objectType, jsonObject);
            serializer.Populate(jsonObject.CreateReader(), target); 
            ((IDataBag)target).Data = jsonObject.ToString(); 
            return target;
        }
        return null;
    }

}

[JsonConverter(typeof(JsonDataBagCreationConverter<Telephone>))]
public class Telephone : ITelephone
{
    public string Name { get; set; }
    public string AreaCode { get; set; }
    public string Number { get; set; }
    public SubPhone SubPhone { get; set; }

    public object Data { get; set; }
    public DataBagTypeEnum DataBagType_Enum { get; set; }
}

あなたからのご連絡をお待ちしております、ありがとう

1月

4

1 に答える 1

1

解決済み:

public class JsonDataBagCreationConverter<T> : JsonConverter where T:IDataBag 
{

//, new() prevented us from using interfaces. Activator.CreateInstance did the trick in Create

//Used when the object decorated with  [JsonConverter(typeof(JsonDataBagCreationConverter<xxxx>))] is de-serialized
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var  jsonObject = JObject.Load(reader);

        if (objectType.IsInterface)
        {
            // Interfaces cannot be instantiated but must be converted to their "real" implemented type
            // Because we serialize with settings.TypeNameHandling = TypeNameHandling.Objects; 
            // A $type property is added to the json by the deserializer.
            string type = jsonObject["$type"].ToString();
            var typesAsArray = type.Split(',');
            var wrappedTarget = Activator.CreateInstance(typesAsArray[1], typesAsArray[0]);
            var realTarget = wrappedTarget.Unwrap() as IDataBag; 
            serializer.Populate(jsonObject.CreateReader(), realTarget); // Will call this function recursively for any objects that have JsonDataBagCreationConverter as attribute
            ((IDataBag)realTarget).Data = jsonObject.ToString(); // This is where custom data is stored in databag
            return realTarget; 
        }

        // Non interface
        var target = Create(objectType, jsonObject);
        serializer.Populate(jsonObject.CreateReader(), target); // Will call this function recursively for any objects that have JsonDataBagCreationConverter as attribute
        ((IDataBag)target).Data = jsonObject.ToString(); // This is where custom data is stored in databag
        return target;


}

public override bool CanRead
{
    get
    {
        return true; 
    }
}

public override bool CanWrite
{
    get
    {
        return false; 
    }
}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
    throw new Exception("WriteJson not implemented");
}

protected IDataBag Create(Type objectType, JObject jsonObject)
{
    var aa = Activator.CreateInstance(objectType);
    return aa as IDataBag;
    // return new T(); // this demands ,new() on the class and then it will not work with interfaces
}

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

}

于 2012-10-10T08:34:27.700 に答える