You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用MessagePack序列化含JObject的Dictionary<string,object>报错如何解决?

解决MessagePack序列化JObject时的泛型约束错误

问题场景

需要将任意类序列化为二进制格式,因BinaryFormatter已被弃用选择MessagePack,但序列化包含JObject的Dictionary<string, object>时抛出错误。

代码示例

public class Foo
{
  public Dictionary<string, object> Bar { get; set; }
}

var foo = new Foo { Bar = new Dictionary<string, object>() };
foo.Bar.Add("binding", JObject.Parse(@"{
  ""source"": ""EventRegistrationFormDataSource"",
  ""inputs"": {
    ""sourceType"": {
      ""value"": ""msevtmgt_event""
    }
  },
  ""outputPath"": ""msevtmgt_description"",
  ""outputType"": ""memo""
}"));

var options = TypelessContractlessStandardResolver.Options;
MessagePackSerializer.Serialize(foo, options);

错误信息

System.ArgumentException: 泛型参数[0]“Newtonsoft.Json.Linq.JContainer”违反了“MessagePack.Formatters.NonGenericListFormatter`1[T]”的类型约束。

堆栈跟踪: 
    RuntimeTypeHandle.Instantiate(RuntimeType inst)
    RuntimeType.MakeGenericType(Type[] instantiation)
    --- 内部异常堆栈跟踪结束 ---
    RuntimeType.ValidateGenericArguments(MemberInfo definition, RuntimeType[] genericArguments, Exception e)
    RuntimeType.MakeGenericType(Type[] instantiation)
    DynamicGenericResolverGetFormatterHelper.GetFormatter(Type t)
    FormatterCache`1.cctor()
    --- 来自之前位置的堆栈跟踪结束 ---
    FormatterResolverExtensions.Throw(TypeInitializationException ex)
    Serialize(Byte[][], Object[], MessagePackWriter&, JProperty, MessagePackSerializerOptions)
    <4 more frames...>
    DictionaryFormatterBase`5.Serialize(MessagePackWriter& writer, TDictionary value, MessagePackSerializerOptions options)
    Serialize(Byte[][], Object[], MessagePackWriter&, Foo, MessagePackSerializerOptions)
    AnonymousSerializableFormatter`1.Serialize(MessagePackWriter& writer, T value, MessagePackSerializerOptions options)
    MessagePackSerializer.Serialize[T](MessagePackWriter& writer, T value, MessagePackSerializerOptions options)

解决方案

错误根源是MessagePack默认解析器无法处理Newtonsoft.Json.Linq系列类型(如JObject、JContainer),这些类型不满足NonGenericListFormatter的泛型约束。以下是三种可行解决方式:

1. 自定义JObject格式化器

实现专门处理JObject的格式化器,序列化时将其转为字典,反序列化时再转回JObject:

public class JObjectMessagePackFormatter : IMessagePackFormatter<JObject>
{
    public void Serialize(ref MessagePackWriter writer, JObject value, MessagePackSerializerOptions options)
    {
        var dict = value.ToObject<Dictionary<string, object>>();
        options.Resolver.GetFormatter<Dictionary<string, object>>().Serialize(ref writer, dict, options);
    }

    public JObject Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
    {
        var dict = options.Resolver.GetFormatter<Dictionary<string, object>>().Deserialize(ref reader, options);
        return JObject.FromObject(dict);
    }
}

注册格式化器到解析器:

var options = MessagePackSerializerOptions.Create(new CompositeResolver(
    new IMessagePackFormatter[] { new JObjectMessagePackFormatter() },
    new IFormatterResolver[] { TypelessContractlessStandardResolver.Instance }
));

MessagePackSerializer.Serialize(foo, options);

2. 提前转换JObject为字典

如果不需要保留JObject类型,添加到字典前直接转为Dictionary<string, object>:

var jsonString = @"{
  ""source"": ""EventRegistrationFormDataSource"",
  ""inputs"": {
    ""sourceType"": {
      ""value"": ""msevtmgt_event""
    }
  },
  ""outputPath"": ""msevtmgt_description"",
  ""outputType"": ""memo""
}";
foo.Bar.Add("binding", JObject.Parse(jsonString).ToObject<Dictionary<string, object>>());

3. 使用MessagePack的Newtonsoft.Json扩展库

安装MessagePack.NewtonsoftJson包后,直接使用现成的解析器处理JObject:

var options = MessagePackSerializerOptions.Create(new CompositeResolver(
    new IFormatterResolver[] { NewtonsoftJsonResolver.Instance },
    new IFormatterResolver[] { TypelessContractlessStandardResolver.Instance }
));

MessagePackSerializer.Serialize(foo, options);

内容的提问来源于stack exchange,提问作者Ondrej Svejdar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 12:44:57