C# json.net ExtensionData在反序列化时修改json键名
我使用了C# json.net ExtensionData在反序列化时修改json键名,c#,json.net,deserialization,C#,Json.net,Deserialization,我使用了JsonExtensionData属性和字典,它实际上对我所有的“未知”JSON结果都非常有效 不幸的是,我从Web服务获得的JSON字符串有时会给我非字母数字字符的键,我希望在反序列化过程中清除这些字符 例如: "dc:title":"My Document title" 在反序列化过程中,我想删除所有非字母数字字符,我想知道是否有一种简单的方法可以使用自定义转换器来实现这一点 反序列化程序代码 public class TikaDeserializer : IDeserialize
JsonExtensionData
属性和字典
,它实际上对我所有的“未知”JSON结果都非常有效
不幸的是,我从Web服务获得的JSON字符串有时会给我非字母数字字符的键,我希望在反序列化过程中清除这些字符
例如:
"dc:title":"My Document title"
在反序列化过程中,我想删除所有非字母数字字符,我想知道是否有一种简单的方法可以使用自定义转换器来实现这一点
反序列化程序代码
public class TikaDeserializer : IDeserializer
{
private Newtonsoft.Json.JsonSerializer serializer;
public TikaDeserializer(Newtonsoft.Json.JsonSerializer serializer)
{
this.serializer = serializer;
}
public T Deserialize<T>(RestSharp.IRestResponse response)
{
var content = response.Content;
using(var stringReader = new StringReader(content))
{
using(var jsonTextReader = new JsonTextReader(stringReader))
{
return serializer.Deserialize<T>(jsonTextReader);
}
}
}
public string DateFormat { get; set; }
public string Namespace { get; set; }
public string RootElement { get; set; }
public static TikaDeserializer Default
{
get
{
return new TikaDeserializer(new Newtonsoft.Json.JsonSerializer()
{
NullValueHandling = NullValueHandling.Ignore,
});
}
}
公共类TikaDeserializer:IDeserializer
{
私有Newtonsoft.Json.Json序列化程序;
公共TikaDeserializer(Newtonsoft.Json.Json序列化程序)
{
this.serializer=序列化程序;
}
公共T反序列化(RestSharp.IRestResponse响应)
{
var content=response.content;
使用(var stringReader=新的stringReader(内容))
{
使用(var jsonTextReader=newjsontextreader(stringReader))
{
返回序列化程序。反序列化(jsonTextReader);
}
}
}
公共字符串日期格式{get;set;}
公共字符串命名空间{get;set;}
公共字符串根元素{get;set;}
公共静态反序列化程序默认值
{
得到
{
返回新的TikaDeserializer(新的Newtonsoft.Json.JsonSerializer()
{
NullValueHandling=NullValueHandling.Ignore,
});
}
}
Gediminas的转换器代码
public class InputKeyNameCleanerConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType.IsGenericType && objectType.GetGenericTypeDefinition() == typeof(Dictionary<,>);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var jObject = JToken.ReadFrom(reader);
foreach(JToken token in jObject.ToList())
{
string replacedName = Regex.Replace(token.Path, @"[^A-Za-z]", String.Empty);
JProperty newToken = new JProperty(replacedName, token.First);
token.Replace(newToken);
}
return jObject.ToObject(objectType);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotSupportedException();
}
}
公共类InputKeyNameCleanerConverter:JsonConverter
{
公共覆盖布尔CanConvert(类型objectType)
{
返回objectType.IsGenericType&&objectType.GetGenericTypeDefinition()==typeof(字典);
}
公共重写对象ReadJson(JsonReader阅读器,类型objectType,对象existingValue,JsonSerializer序列化程序)
{
var jObject=JToken.ReadFrom(读卡器);
foreach(jObject.ToList()中的JToken令牌)
{
string replacedName=Regex.Replace(token.Path,@“[^A-Za-z]”,string.Empty);
JProperty newToken=新的JProperty(replacedName,token.First);
代币。替换(纽顿);
}
返回jObject.ToObject(objectType);
}
公共重写void WriteJson(JsonWriter编写器、对象值、JsonSerializer序列化器)
{
抛出新的NotSupportedException();
}
}
模型
公共类解析文档
{
[JsonProperty(“作者”)]
公共字符串作者{get;set;}
[JsonProperty(“内容类型”)]
公共字符串ContentType{get;set;}
[JsonProperty(“内容编码”)]
公共字符串ContentEncoding{get;set;}
[JsonProperty(“创建日期”)]
公共日期时间?DateCreated{get;set;}
[JsonProperty(“上次修改”)]
公共日期时间?日期修改{get;set;}
[JsonProperty(“上次保存日期”)]
公共日期时间?已保存日期{get;set;}
[JsonProperty(“上次打印”)]
公共日期时间?已日期打印的{get;set;}
[JsonProperty(“所有权”)]
公共字符串标题{get;set;}
[JsonProperty(“X-TIKA:content”)]
公共字符串内容{get;set;}
[JsonExtensionData]
公共字典元数据{get;set;}
}
当然可以!您可以使用正则表达式。您可以使用[^a-zA-Z0-9]
匹配任何非字母数字字符,并将其替换为空字符串。在JsonConverter
中,您可以创建一个JObject
并迭代其属性,将其替换为具有正确名称的属性
我提出了一个通用解决方案,它接受一个Regex
对象和一个replacement
字符串作为构造函数参数:
实施:
class DictionaryRegexReplaceJsonConverter : JsonConverter
{
public Regex ReplacingRegex { get; set; }
public string Replacement { get; set; }
public DictionaryRegexReplaceJsonConverter(Regex replacingRegex, string replacement = "")
{
ReplacingRegex = replacingRegex;
Replacement = replacement;
}
public override bool CanConvert(Type objectType)
{
return objectType.IsGenericType && objectType.GetGenericTypeDefinition() == typeof(Dictionary<,>);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var jo = JToken.ReadFrom(reader);
foreach (JToken token in jo.ToList())
{
string replacedName = ReplacingRegex.Replace(token.Path, Replacement);
JProperty newToken = new JProperty(replacedName, token.First);
token.Replace(newToken);
}
return jo.ToObject(objectType);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotSupportedException();
}
}
Regex regex = new Regex("[^a-zA-Z0-9]");
var converter = new DictionaryKeyReplacingJsonConverter(regex);
string json = "{\"dc:title\":\"My Document title\", \"Another Example!\": \"foo\"}";
// {"dctitle": "My Document title", "AnotherExample": "foo"} ]
var obj = JsonConvert.DeserializeObject<Dictionary<string, object>>(json, converter);
类字典RegexReplaceJSONConverter:JsonConverter
{
公共正则表达式ReplacingRegex{get;set;}
公共字符串替换{get;set;}
公共字典regexreplacejsonconverter(Regex replacingRegex,string replacement=“”)
{
ReplacingRegex=ReplacingRegex;
替换=替换;
}
公共覆盖布尔CanConvert(类型objectType)
{
返回objectType.IsGenericType&&objectType.GetGenericTypeDefinition()==typeof(字典);
}
公共重写对象ReadJson(JsonReader阅读器,类型objectType,对象existingValue,JsonSerializer序列化程序)
{
var jo=JToken.ReadFrom(读取器);
foreach(jo.ToList()中的JToken令牌)
{
字符串replacedName=ReplacingRegex.Replace(token.Path,Replacement);
JProperty newToken=新的JProperty(replacedName,token.First);
代币。替换(纽顿);
}
返回jo.ToObject(objectType);
}
公共重写void WriteJson(JsonWriter编写器、对象值、JsonSerializer序列化器)
{
抛出新的NotSupportedException();
}
}
用法:
class DictionaryRegexReplaceJsonConverter : JsonConverter
{
public Regex ReplacingRegex { get; set; }
public string Replacement { get; set; }
public DictionaryRegexReplaceJsonConverter(Regex replacingRegex, string replacement = "")
{
ReplacingRegex = replacingRegex;
Replacement = replacement;
}
public override bool CanConvert(Type objectType)
{
return objectType.IsGenericType && objectType.GetGenericTypeDefinition() == typeof(Dictionary<,>);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var jo = JToken.ReadFrom(reader);
foreach (JToken token in jo.ToList())
{
string replacedName = ReplacingRegex.Replace(token.Path, Replacement);
JProperty newToken = new JProperty(replacedName, token.First);
token.Replace(newToken);
}
return jo.ToObject(objectType);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotSupportedException();
}
}
Regex regex = new Regex("[^a-zA-Z0-9]");
var converter = new DictionaryKeyReplacingJsonConverter(regex);
string json = "{\"dc:title\":\"My Document title\", \"Another Example!\": \"foo\"}";
// {"dctitle": "My Document title", "AnotherExample": "foo"} ]
var obj = JsonConvert.DeserializeObject<Dictionary<string, object>>(json, converter);
Regex Regex=new Regex(“[^a-zA-Z0-9]”);
var转换器=新字典YKEYReplacingJSONConverter(正则表达式);
字符串json=“{\”dc:title\”:\“我的文档标题\”,\“另一个示例!\”:\“foo\”};
//{“dctitle”:“我的文档标题”,“另一个示例”:“foo”}]
var obj=JsonConvert.DeserializeObject(json,转换器);
如果考虑性能,可以通过手动读取JsonReader
并形成对象,而不是使用JObject并替换属性来优化此操作。您可以使用替换委托的:
public class ExtensionNameMappingContractResolver : IContractResolver
{
readonly IContractResolver baseResolver;
readonly Regex regex;
readonly string replacement;
// As of 7.0.1, Json.NET suggests using a static instance for "stateless" contract resolvers, for performance reasons.
// http://www.newtonsoft.com/json/help/html/ContractResolver.htm
// http://www.newtonsoft.com/json/help/html/M_Newtonsoft_Json_Serialization_DefaultContractResolver__ctor_1.htm
// "Use the parameterless constructor and cache instances of the contract resolver within your application for optimal performance."
static ExtensionNameMappingContractResolver removeNonAlphanumericCharactersInstance;
static ExtensionNameMappingContractResolver()
{
// Regex is from https://stackoverflow.com/questions/8779189/how-do-i-strip-non-alphanumeric-characters-including-spaces-from-a-string
removeNonAlphanumericCharactersInstance = new ExtensionNameMappingContractResolver(new DefaultContractResolver(), new Regex(@"[^\p{L}\p{N}]+"), "");
}
public static ExtensionNameMappingContractResolver RemoveNonAlphanumericCharactersInstance { get { return removeNonAlphanumericCharactersInstance; } }
public ExtensionNameMappingContractResolver(IContractResolver baseResolver, Regex regex, string replacement)
{
if (regex == null || replacement == null || baseResolver == null)
throw new ArgumentNullException();
this.regex = regex;
this.replacement = replacement;
this.baseResolver = baseResolver;
}
#region IContractResolver Members
public JsonContract ResolveContract(Type type)
{
var contract = baseResolver.ResolveContract(type);
if (contract is JsonObjectContract)
{
var objContract = (JsonObjectContract)contract;
if (objContract.ExtensionDataSetter != null)
{
var oldSetter = objContract.ExtensionDataSetter;
objContract.ExtensionDataSetter = (o, key, value) =>
{
var newKey = regex.Replace(key, replacement);
oldSetter(o, newKey, value);
};
}
}
return contract;
}
#endregion
}
然后像这样使用它:
var settings = new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore,
ContractResolver = ExtensionNameMappingContractResolver.RemoveNonAlphanumericCharactersInstance
};
var serializer = JsonSerializer.CreateDefault(settings);
请注意,我使用的Regex
替换了由定义的所有Unicode非字母数字字符。有关更多选项,包括删除所有非ASCII、非字母数字字符,请参阅
请注意,如果通过从属性名称中删除非字母数字字符,契约解析程序尝试添加重复的扩展数据键,则会出现JsonSerializationException