我使用Newtonsoft.Json库
有没有办法在反序列化期间从任何字符串数据中修剪空格?
class Program
{
class Person
{
[JsonProperty("name")]
public string Name;
}
static void Main(string[] args)
{
var p = JsonConvert.DeserializeObject<Person>(@"{ name: "" John "" }");
Console.WriteLine("Name is: "{0}"", p.Name);
}
}
添加:
最后,我有了自定义转换器的解决方案。不好,但比Trim((的物业更好。
如果有人有任何想法如何以更自然的方式做到这一点,欢迎。
class Program
{
sealed class TrimAttribute : Attribute
{ }
class TrimConverter<T> : JsonConverter where T : new()
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var jObject = JObject.Load(reader);
var obj = new T();
serializer.Populate(jObject.CreateReader(), obj);
var props = objectType.GetFields(BindingFlags.Instance | BindingFlags.Public)
.Where(p => p.FieldType == typeof(string))
.Where(p => Attribute.GetCustomAttributes(p).Any(u => (Type) u.TypeId == typeof(TrimAttribute)))
;
foreach (var fieldInfo in props)
{
var val = (string) fieldInfo.GetValue(obj);
fieldInfo.SetValue(obj, val.Trim());
}
return obj;
}
public override bool CanConvert(Type objectType)
{
return objectType.IsAssignableFrom(typeof (T));
}
}
[JsonConverter(typeof(TrimConverter<Person>))]
class Person
{
[JsonProperty("name")]
[Trim]
public string Name;
[JsonProperty("surname")]
public string Surname;
}
static void Main(string[] args)
{
var p = JsonConvert.DeserializeObject<Person>(@"{ name: "" John "", surname: "" Smith "" }");
Console.WriteLine("Name is: "{0}", "{1}"", p.Name, p.Surname);
}
}
你可以
写你自己的JsonConverter
:
public class TrimmingConverter : JsonConverter
{
public override bool CanRead => true;
public override bool CanWrite => false;
public override bool CanConvert(Type objectType) => objectType == typeof(string);
public override object ReadJson(JsonReader reader, Type objectType,
object existingValue, JsonSerializer serializer)
{
return ((string)reader.Value)?.Trim();
}
public override void WriteJson(JsonWriter writer, object value,
JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
您可以像这样使用它来应用于所有字符串字段:
var json = @"{ name:"" John "" }"
var p = JsonConvert.DeserializeObject<Person>(json, new TrimmingConverter());
Console.WriteLine("Name is: "{0}"", p.Name);
//Name is: "John"
或者,您可以仅将其应用于某些字段:
public class Person
{
[JsonProperty("name")]
[JsonConverter(typeof(TrimmingConverter))] // <-- that's the important line
public string Name { get; set; }
[JsonProperty("other")]
public string Other { get; set; }
}
var json = @"{ name:"" John "", other:"" blah blah blah "" }"
var p = JsonConvert.DeserializeObject<Person>(json);
Console.WriteLine("Name is: "{0}"", p.Name);
Console.WriteLine("Other is: "{0}"", p.Other);
//Name is: "John"
//Other is: " blah blah blah "
在 .NET Core 3.1 中,您可以使用System.Text.Json
来实现此目的。
/// <summary>
/// Trim leading and trailing whitespace.
/// </summary>
public class TrimmingConverter : JsonConverter<string>
{
/// <summary>
/// Trim the input string
/// </summary>
/// <param name="reader">reader</param>
/// <param name="typeToConvert">Object type</param>
/// <param name="options">Existing Value</param>
/// <returns></returns>
public override string Read(
ref Utf8JsonReader reader,
Type typeToConvert,
JsonSerializerOptions options) => reader.GetString()?.Trim();
/// <summary>
/// Trim the output string
/// </summary>
/// <param name="writer">Writer</param>
/// <param name="value">value</param>
/// <param name="options">serializer</param>
public override void Write(
Utf8JsonWriter writer,
string value,
JsonSerializerOptions options) => writer.WriteStringValue(value?.Trim());
}
上面
提供的解决方案对我不起作用。我修改了Sam Fisher解决方案,并将其与Timmerz解决方案相结合。如何通过反射在一次调用中获取字段和属性?
public sealed class TrimAttribute : Attribute {
}
public static class TrimConverterExtension {
public static void SetValue(this MemberInfo member, object property, object value) {
switch (member.MemberType) {
case MemberTypes.Property:
((PropertyInfo)member).SetValue(property, value, null);
break;
case MemberTypes.Field:
((FieldInfo)member).SetValue(property, value);
break;
default:
throw new Exception("Property must be of type FieldInfo or PropertyInfo");
}
}
public static object GetValue(this MemberInfo member, object property) {
switch (member.MemberType) {
case MemberTypes.Property:
return ((PropertyInfo)member).GetValue(property, null);
case MemberTypes.Field:
return ((FieldInfo)member).GetValue(property);
default:
throw new Exception("Property must be of type FieldInfo or PropertyInfo");
}
}
public static Type GetMemberType(this MemberInfo member) {
switch (member.MemberType) {
case MemberTypes.Field:
return ((FieldInfo)member).FieldType;
case MemberTypes.Property:
return ((PropertyInfo)member).PropertyType;
case MemberTypes.Event:
return ((EventInfo)member).EventHandlerType;
default:
throw new ArgumentException("MemberInfo must be if type FieldInfo, PropertyInfo or EventInfo", "member");
}
}
}
public class TrimConverter<T> : JsonConverter where T : new() {
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) {
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) {
var jObject = JObject.Load(reader);
var obj = new T();
serializer.Populate(jObject.CreateReader(), obj);
//Looks for the trim attribute on the property
const BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance;
IEnumerable<MemberInfo> members = objectType.GetFields(bindingFlags).Cast<MemberInfo>()
.Concat(objectType.GetProperties(bindingFlags))
.Where(p => p.GetMemberType() == typeof(string))
.Where(p => Attribute.GetCustomAttributes(p).Any(u => (Type)u.TypeId == typeof(TrimAttribute)))
.ToArray();
foreach (var fieldInfo in members) {
var val = (string)fieldInfo.GetValue(obj);
if (!string.IsNullOrEmpty(val)) {
fieldInfo.SetValue(obj, val.Trim());
}
}
return obj;
}
public override bool CanConvert(Type objectType) {
return objectType.IsAssignableFrom(typeof(T));
}
}