我有一些带有本地化文本的.NET类;即英文文本,西班牙语相应文本等。我们有一个Locale类,如下所示:
class Locale
{
int Id;
string Abbreviation; // e.g. "en"
string Name; // e.g. "English"
static Locale FromAbbreviation(string abbreviation);
}
本地化文本存储在IDictionary属性中,类似于
class Document
{
IDictionary<Locale, string> Content;
}
当序列化为JSON时,我希望这可以通过locale缩写来键入,因此序列化的Document对象看起来像这样:
{
"content": {
"en": "English content",
"es": "Spanish content"
}
}
我需要一个ContractResolver,它将IDictionary<Locale, string>
对象转换为Dictionary<string, string>
对象,在序列化期间使用Locale.Abbreviation属性作为键,并在反序列化时调用Locale.FromAbbreviation()来转换密钥回到Locale对象。
我查看了JSON.NET文档和各种Stackoverflow问题,似乎没有一种简单的方法(至少我找不到它)。我确实发现了看起来像straightforward way to do the same thing using a TypeConverter attribute的东西,但我宁愿不从我的域类中依赖Json.NET。使用ContractResolver有合理的方法吗?
答案 0 :(得分:2)
这里你真的不需要ContractResolver
。您可以使用自定义JsonConverter
来处理从Dictionary<Locale, string>
到所需JSON的转换,而无需在模型类中使用属性。只要转换器的CanConvert
方法被正确编码以识别转换器处理的字典类型,您就可以将转换器添加到序列化器设置中,Json.Net将找到它并正确使用它。
以下是转换器的外观:
class LocaleDictionaryConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof(IDictionary<Locale, string>).IsAssignableFrom(objectType);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject obj = JObject.Load(reader);
IDictionary<Locale, string> dict = (IDictionary<Locale, string>)existingValue ?? new Dictionary<Locale, string>();
foreach (var prop in obj.Properties())
{
dict.Add(Locale.FromAbbreviation(prop.Name), (string)prop.Value);
}
return dict;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
IDictionary<Locale, string> dict = (IDictionary<Locale, string>)value;
JObject obj = new JObject();
foreach (var kvp in dict)
{
obj.Add(kvp.Key.Abbreviation, kvp.Value);
}
obj.WriteTo(writer);
}
}
以下是如何使用它来序列化:
var settings = new JsonSerializerSettings();
settings.Converters.Add(new LocaleDictionaryConverter());
settings.Formatting = Formatting.Indented;
string json = JsonConvert.SerializeObject(document, settings);
反序列化:
// same settings as above
var document = JsonConvert.DeserializeObject<Document>(json, settings);