gpt4 book ai didi

c# - 有没有办法让 JSON.Net 使用隐式转换而不是其实际类型来序列化对象?

转载 作者:行者123 更新时间:2023-11-30 18:13:52 24 4
gpt4 key购买 nike

考虑这个接口(interface)和类...

public interface IValueHolder{}

public class ValueHolder<TValue> : IValueHolder {

public ValueHolder(TValue value) => this.value = value;
public TValue value { get; }

public static implicit operator ValueHolder<TValue>(TValue value) => new ValueHolder<TValue>(value);
public static implicit operator TValue(ValueHolder<TValue> valueHolder) => valueHolder.value;
}

class ValueStorage : Dictionary<string, IValueHolder>{}

注意与 TValue 之间的隐式转换.

这段代码的要点是我试图存储键/值对,其中值可以是任何类型,但没有装箱惩罚。这是可能的,因为在设置或从存储中检索值时我总是知道类型。 (这就是为什么我不只使用 Dictionary<string, object> 的原因。)

现在考虑这段代码...

var storage = new ValueStorage();

storage["UltimateQuestion"] = new ValueHolder<string>("What do you get when you multiply six by nine?");
storage["UltimateAnswer"] = new ValueHolder<int>(42);

var jsonSerializerSettings = new JsonSerializerSettings{
TypeNameHandling = TypeNameHandling.None,
Formatting = Formatting.Indented,
NullValueHandling = NullValueHandling.Ignore
};

var jsonString = JsonConvert.SerializeObject(storage, jsonSerializerSettings);

结果是这样的……

{
"UltimateQuestion": {
"value": "What do you get when you multiply six by nine?"
},
"UltimateAnswer": {
"value": 42
}
}

我希望与 TValue 之间的隐式转换, 这是 stringint分别,它会给我这个...

{
"UltimateQuestion": "What do you get when you multiply six by nine?",
"UltimateAnswer": 42
}

那么我怎样才能得到ValueStorage<T>序列化和反序列化为 T ?我不介意编写自定义转换器(前提是它们是通用的并且可以基于 TValue )或自定义 SettingsContractResolver子类,但我不确定从哪里开始。

更新

我越想越觉得这实际上是无法解决的。这是因为虽然序列化很容易,但反序列化需要知道 TValue 的类型。 ,它们没有以我想要的格式存储在 JSON 中,因此它不能被反序列化。 (即使上面带有嵌套对象的原始输出也有同样的问题。您需要类型信息才能以任何容量工作。)

但是,为了不让这个问题悬而未决,存储 TValue 类型信息的转换器怎么样?而不是 ValueHolder<TValue>

例如

{
"UltimateQuestion": {
"$type": "[Whatever TValue is--string here]",
"value": "What do you get when you multiply six by nine?"
},
"UltimateAnswer": {
"$type": "[Whatever TValue is--int here]",
"value": 42
}
}

这样转换器就可以重构 ValueHolder<TValue>反序列化期间的实例。它并不完美,但至少可以在不暴露 ValueHolder 框架的情况下进行适当的反序列化。

最佳答案

您可以编写一个转换器(参见 https://www.newtonsoft.com/json/help/html/CustomJsonConverter.htm)。

public class ValueHolderJsonConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
serializer.Serialize(writer, ((IValueHolder)value).value);
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
return Activator.CreateInstance(objectType, serializer.Deserialize(reader));
}

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

请注意,我向您的接口(interface)添加了一个非泛型“值”属性,以便在无需使用反射的情况下获取值而无需考虑实际的泛型类型:

public interface IValueHolder{
object value { get; }
}

public class ValueHolder<TValue> : IValueHolder
{
// as before

object IValueHolder.value => (object)value;
}

要使用它,您需要创建一个新的 JsonSerializerSettings 类(或附加您现有的类):

var settings = new JsonSerializerSettings {
Converters = {
new ValueHolderJsonConverter()
};

并将其作为参数提供给 SerializeObject 和 DeserializeObject。

关于c# - 有没有办法让 JSON.Net 使用隐式转换而不是其实际类型来序列化对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51816301/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com