我想将JSON中使用的密钥转换为不同的语言。
从设计的角度来看,我知道在设计接口,API等时这似乎是胡说八道。为什么不首先使用英语?好吧,我没有写这个要求;)
/// <summary>serialization language</summary>
public enum Language
{
/// <summary>English</summary>
EN,
/// <summary>German</summary>
DE
// some more ...
}
最简单的方法可能是属性:
/// <summary>An Attribute to add different "translations"</summary>
public class TranslatedFieldName : Attribute
{
public string Name { get; }
public Language Lang{ get; }
// actually there might be a dictionary with lang-name pairs later on; but let's keep it simple
public TranslatedFieldName(string translatedName, Language lang)
{
this.Lang = lang;
this.Name = translatedName;
}
}
然后将这个属性添加到我要序列化的类中:
/// <summary>I want to serialize classes of this kind to json in different languages </summary>
public class TranslatableObject
{
[TranslatedFieldName("deutscher_schluessel", Language.DE)]
public string english_key;
}
并致电JsonConvert.SerializeObject(...)
public void SerializationMethod()
{
TranslatableObject to = new TranslatableObject()
{
english_key = "foo bar"
};
string englishJson = JsonConvert.SerializeObject(to); // == { "english_key": "foo bar" }
string germanJson = JsonConvert.SerializeObject(to, new MultiLangConverter(Language.DE); // == { "deutscher_schluessel": "foo bar" }
}
我不知道用过的MultiLangConverter
的实际外观如何:
public class MultiLangConverter : JsonConverter
{
private readonly Language _lang,
public MultiLangConverter() : this(Language.EN) { }
public MultiLangConverter(Language lang)
{
_lang = lang;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException("Out of scope for now");
}
public override bool CanRead
{
get { return false; } // out of scope for now
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
// what goes here?
}
}
我尝试过的所有尝试似乎都过于复杂。我真的需要一个JsonConverter吗?还是更适合使用ContractResolver?
答案 0 :(得分:5)
我认为您可以使用属性来表示已翻译的字段名称,这是正确的选择,但我认为您最终将希望使用自定义ContractResolver
来处理翻译,而不是使用JsonConverter
,尤其是如果您需要对多个模型类进行翻译(可能会发生)。
这是解析器的外观:
public class MultiLangResolver : DefaultContractResolver
{
public Language Language { get; set; }
public MultiLangResolver(Language lang)
{
Language = lang;
}
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
JsonProperty prop = base.CreateProperty(member, memberSerialization);
// See if there is a [TranslatedFieldName] attribute applied to the property
// for the requested language
var att = prop.AttributeProvider.GetAttributes(true)
.OfType<TranslatedFieldNameAttribute>()
.FirstOrDefault(a => a.Lang == Language);
// if so, change the property name to the one from the attribute
if (att != null)
{
prop.PropertyName = att.Name;
}
return prop;
}
}
这是使用解析器进行序列化的方式:
public static string Serialize(object obj, Language lang)
{
var settings = new JsonSerializerSettings
{
ContractResolver = new MultiLangResolver(lang),
Formatting = Formatting.Indented
};
var json = JsonConvert.SerializeObject(obj, settings);
return json;
}
另一个注意事项:您将要用TranslatedFieldNameAttribute
属性标记您的[AttributeUsage]
类,该属性表示该类可以在属性上使用并且可以多次应用(一次针对每种所需的语言)支持):
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true, Inherited = true)]
public class TranslatedFieldNameAttribute : Attribute
{
...
}
正在运行的演示:https://dotnetfiddle.net/lIQaJc