我使用JsonExtensionData
属性和Dictionary<string, object>
,这对我所有的&#34;未知&#34;实际上非常有效。 JSON结果。
不幸的是,我从我的webservice获得的JSON字符串有时会给我带有非字母数字字符的键,我想在反序列化时清理它。
例如:
"dc:title":"My Document title"
在反序列化期间,我想删除所有非字母数字字符,我想知道是否有一种简单的方法可以使用自定义转换器?
Derserializer Code
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,
});
}
}
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();
}
}
模型
public class ParsedDocument
{
[JsonProperty("Author")]
public string Author { get; set; }
[JsonProperty("Content-Type")]
public string ContentType { get; set; }
[JsonProperty("Content-Encoding")]
public string ContentEncoding { get; set; }
[JsonProperty("Creation-Date")]
public DateTime? DateCreated { get; set; }
[JsonProperty("Last-Modified")]
public DateTime? DateModified { get; set; }
[JsonProperty("Last-Save-Date")]
public DateTime? DateSaved { get; set; }
[JsonProperty("Last-Printed")]
public DateTime? DatePrinted { get; set; }
[JsonProperty("title")]
public string Title { get; set; }
[JsonProperty("X-TIKA:content")]
public string Content { get; set; }
[JsonExtensionData]
public Dictionary<string, object> MetaData { get; set; }
}
答案 0 :(得分:1)
您可以使用替换custom contract resolver代表的JsonObjectContract.ExtensionDataSetter
执行此操作:
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
会替换table of Unicode character categories定义的所有 Unicode 非字母数字字符。有关更多选项,包括删除所有非ASCII,非字母数字字符,请参阅How do I strip non-alphanumeric characters (including spaces) from a string?。
请注意,如果通过从属性名称中删除非字母数字字符,合同解析程序会尝试添加重复的扩展数据键,则会引发JsonSerializationException: Error setting value in extension data ---> System.ArgumentException: An item with the same key has already been added
。
答案 1 :(得分:0)
当然!你可以使用正则表达式。您可以使用[^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);
如果关注性能,可以通过手动读取JsonReader
并形成对象来优化,而不是使用JObject和替换属性。