【问题标题】:Serialize an IDictionary<string, object> with GraphQL and Hot Choclate to a dynamic JSON使用 GraphQL 和 Hot Choclate 将 IDictionary<string, object> 序列化为动态 JSON
【发布时间】:2020-06-21 13:31:51
【问题描述】:

我正在使用 Web API 将 Hot Chocolate(GraphQL) 添加到现有的 ASP.Net Core 项目中,并重用 Web API 使用的模型。 其中一个模型具有 IDictionary 属性,该属性通过 Web API 序列化为动态 JSON。

模型

public class Theme
{
    ...
    public IDictionary<string, object> Styles { get; set; }
    ...
}

用Web API可以序列化为

{
  ...
  styles: {
    header: {
      color: "#fff", 
      background: "rgba(255, 255, 255, 0)", 
      boxShadow: "", position: "fixed"},
      ...
    },
    borderRadius: "4px",
    ...
  }
  ...
}

使用 Hot Chocolate,我正在重用模型并在启动时添加 GraphQL

services.AddGraphQL(sp => SchemaBuilder.New()
    .AddServices(sp)
    .AddQueryType(d => d.Name("Query"))
    ...
    .AddType<Theme>()
    .Create());

生成的架构变成

type Theme {
  ...
  styles: [KeyValuePairOfStringAndObject!]
  ...
}

只能检索密钥

{
  themes(...) {
    edges {
      node {
        name
        styles{
          key
        }
      }
    }
  }
}

回复如下

{
  "themes": {
    "edges": [
      {
        "node": {
          ...
          "styles": [
            {
              "key": "header"
            },
            {
              "key": "borderRadius"
            },
            ...
          ]
        }
      }
    ]
  }
}

我想设置 Hot Chocolate 以使编写 GraphQL 查询成为可能,该查询提供与 Web API 相同的动态结果。

更新

源是一个 JSON 字符串,它被反序列化为 Dictionary

var jsonString = "{\"header\":{\"color\":\"#fff\"},\"borderRadius\":\"4px\"}";

theme.Styles = JsonConvert.DeserializeObject<Dictionary<string, object>>(jsonString);

问题是生成的字典没有递归序列化为 Dictionary

【问题讨论】:

    标签: asp.net graphql hotchocolate


    【解决方案1】:

    Hot Chocolate 具有适用于动态数据结构的 AnyType。但是默认情况下 AnyType 不是从类型中隐式推断出来的。

    您在这里基本上有两个选择。使用属性声明类型的类型(或使用 fluent API 执行相同操作)。

    纯代码优先:

    public class Theme
    {
        ...
        [GraphQLType(typeof(AnyType))]
        public IDictionary<string, object> Styles { get; set; }
        ...
    }
    

    带有模式类型的代码优先:

    public class ThemeType : ObjectType<Theme> 
    {
        protected override void Configure(IObjectTypeDescriptor<Theme> descriptor)
        {
            descriptor.Field(t => t.Styles).Type<AnyType>();
        }
    }
    

    或者,您可以说在您的架构中所有IDictionary&lt;string, object&gt; 都是任何类型,在这种情况下您不需要显式定义类型:

    services.AddGraphQL(sp => SchemaBuilder.New()
        .AddServices(sp)
        .AddQueryType(d => d.Name("Query"))
        ...
        .AddType<Theme>()
        .BindClrType<IDictionary<string, object>, AnyType>()
        .Create());
    

    我希望这会有所帮助。

    【讨论】:

    • 首先,我确保使用此答案 stackoverflow.com/a/31250524/3881090 将所有字典反序列化为 Dictionary 然后 Pure Code-first 和 Code-First with Schema Types 都能完美运行。
    • 嗨@Lillvik 你能扩展一下吗?我不确定在哪里是覆盖序列化和反序列化的最佳位置,以避免在查询嵌套的嵌套 json 对象和数组时出现参数计数不匹配错误。
    • 对于字典属性,graphql 查询的外观如何?
    • 有关于使用 Anytype 字段类型过滤字典属性的消息吗?
    猜你喜欢
    • 1970-01-01
    • 2012-07-18
    • 1970-01-01
    • 2018-08-05
    • 1970-01-01
    • 2019-07-03
    • 2010-11-24
    • 2017-11-27
    相关资源
    最近更新 更多