【问题标题】:Ignore ExpandoObject Properties with JSON.Net Serializer Settings使用 JSON.Net 序列化程序设置忽略 ExpandoObject 属性
【发布时间】:2017-03-17 17:21:14
【问题描述】:

是否可以在使用JsonConvert(expando, formatting, serializerSettings) 时忽略ExpandoObject 属性,尤其是Delegate 类型的属性?

基本上我试图忽略此示例扩展对象中 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 -> some generic type -> 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 配合使用。

【问题讨论】:

  • 我有点不清楚你的问题是什么。 序列化时,您是否尝试跳过委托值ExpandoObject 属性?因为听起来你也想反序列化这个示例 json:{ func: () => {} },这是无效的。
  • 更新了该部分以使其更加清晰,这是在将扩展序列化为 json 期间。

标签: json.net edgejs


【解决方案1】:

ExpandoObjectConverter 没有任何自定义代码写入 ExpandoObject。相反,它会覆盖JsonConverter.CanWrite 以返回false,从而允许将expando 一般序列化为IDictionary<string, object>。

因此,您可以自己覆盖 CanWrite 和 WriteJson() 以在序列化之前过滤不需要的键/值对:

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。

【讨论】:

    猜你喜欢
    • 2016-08-27
    • 2023-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多