使用 JSON.Net 序列化程序设置忽略 ExpandoObject 属性
Ignore ExpandoObject Properties with JSON.Net Serializer Settings
是否可以在使用 JsonConvert(expando, formatting, serializerSettings)
时忽略 ExpandoObject
属性,尤其是 Delegate
类型的属性?
本质上,我试图忽略此示例中 expando 对象中 func
属性 的所有解析:
//{
// func: () => {}
//}
Action func = () => {};
dynamic expando = new ExpandoObject();
expando.func = func;
// should be empty object {}
string json = JsonConvert(expando, formatting, serializerSettings);
我尝试的第一件事是覆盖转换器。不幸的是,这不起作用,因为我看到 CanConvert
递归调用 Action
-> DelegateEntry
-> 一些通用类型 -> RuntimeMethodInfo
.
private class ExpandoObjectIgnoreConverter : ExpandoObjectConverter
{
public override bool CanConvert(Type objectType)
{
if (typeof(Delegate).IsAssignableFrom(objectType))
{
return false;
}
return base.CanConvert(objectType);
}
}
一种有效的方法是在序列化设置中使用错误处理程序和合同解析器。当我抛出错误时,属性 的所有进一步处理都将被忽略,即 Action
-> DelegateEntry
-> 一些通用类型 -> RuntimeMethodInfo
。但是,如果可能的话,我想比抛出异常更优雅地做到这一点。
错误处理程序:
serializationSettings.Error = (sender, args) =>
{
if (args.ErrorContext.Error is InvalidCastException)
{
args.ErrorContext.Handled = true;
}
}
合同解析器:
private class ExpandoObjectContractResolver : DefaultContractResolver
{
public override JsonContract ResolveContract(Type type)
{
if (typeof(Delegate).IsAssignableFrom(type))
{
throw new InvalidCastException();
}
else
{
return base.ResolveContract(type);
}
}
}
我正在使用 edge 库从 C# 进程中编写 nodejs 脚本。我试图从 C# 中返回的 javascript 对象中删除函数,因为它们被分配了一个 Delegate
类型,不能很好地与 JsonConvert
.
一起使用
ExpandoObjectConverter
does not have any custom code to write an ExpandoObject
. Instead it overrides JsonConverter.CanWrite
到 return false
从而允许将 expando 一般序列化为 IDictionary<string, object>
.
因此您可以自己覆盖 CanWrite
和 WriteJson()
以在序列化之前过滤不需要的 key/value 对:
public class FilteredExpandoObjectConverter : ExpandoObjectConverter
{
public override bool CanWrite { get { return true; } }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var expando = (IDictionary<string, object>)value;
var dictionary = expando
.Where(p => !(p.Value is System.Delegate))
.ToDictionary(p => p.Key, p => p.Value);
serializer.Serialize(writer, dictionary);
}
}
然后在设置中使用转换器如下:
var formatting = Formatting.Indented;
var serializerSettings = new JsonSerializerSettings
{
Converters = { new FilteredExpandoObjectConverter() },
};
var json = JsonConvert.SerializeObject(expando, formatting, serializerSettings);
请注意,这只会过滤 ExpandoObject
直接拥有的委托值。如果你有一个包含一些委托的集合,或者某些 POCO 中的委托值成员,它们将不会被此代码过滤。
样本fiddle.
是否可以在使用 JsonConvert(expando, formatting, serializerSettings)
时忽略 ExpandoObject
属性,尤其是 Delegate
类型的属性?
本质上,我试图忽略此示例中 expando 对象中 func
属性 的所有解析:
//{
// func: () => {}
//}
Action func = () => {};
dynamic expando = new ExpandoObject();
expando.func = func;
// should be empty object {}
string json = JsonConvert(expando, formatting, serializerSettings);
我尝试的第一件事是覆盖转换器。不幸的是,这不起作用,因为我看到 CanConvert
递归调用 Action
-> DelegateEntry
-> 一些通用类型 -> RuntimeMethodInfo
.
private class ExpandoObjectIgnoreConverter : ExpandoObjectConverter
{
public override bool CanConvert(Type objectType)
{
if (typeof(Delegate).IsAssignableFrom(objectType))
{
return false;
}
return base.CanConvert(objectType);
}
}
一种有效的方法是在序列化设置中使用错误处理程序和合同解析器。当我抛出错误时,属性 的所有进一步处理都将被忽略,即 Action
-> 。但是,如果可能的话,我想比抛出异常更优雅地做到这一点。DelegateEntry
-> 一些通用类型 -> RuntimeMethodInfo
错误处理程序:
serializationSettings.Error = (sender, args) =>
{
if (args.ErrorContext.Error is InvalidCastException)
{
args.ErrorContext.Handled = true;
}
}
合同解析器:
private class ExpandoObjectContractResolver : DefaultContractResolver
{
public override JsonContract ResolveContract(Type type)
{
if (typeof(Delegate).IsAssignableFrom(type))
{
throw new InvalidCastException();
}
else
{
return base.ResolveContract(type);
}
}
}
我正在使用 edge 库从 C# 进程中编写 nodejs 脚本。我试图从 C# 中返回的 javascript 对象中删除函数,因为它们被分配了一个 Delegate
类型,不能很好地与 JsonConvert
.
ExpandoObjectConverter
does not have any custom code to write an ExpandoObject
. Instead it overrides JsonConverter.CanWrite
到 return false
从而允许将 expando 一般序列化为 IDictionary<string, object>
.
因此您可以自己覆盖 CanWrite
和 WriteJson()
以在序列化之前过滤不需要的 key/value 对:
public class FilteredExpandoObjectConverter : ExpandoObjectConverter
{
public override bool CanWrite { get { return true; } }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var expando = (IDictionary<string, object>)value;
var dictionary = expando
.Where(p => !(p.Value is System.Delegate))
.ToDictionary(p => p.Key, p => p.Value);
serializer.Serialize(writer, dictionary);
}
}
然后在设置中使用转换器如下:
var formatting = Formatting.Indented;
var serializerSettings = new JsonSerializerSettings
{
Converters = { new FilteredExpandoObjectConverter() },
};
var json = JsonConvert.SerializeObject(expando, formatting, serializerSettings);
请注意,这只会过滤 ExpandoObject
直接拥有的委托值。如果你有一个包含一些委托的集合,或者某些 POCO 中的委托值成员,它们将不会被此代码过滤。
样本fiddle.