2017-08-30 145 views
18

我们正在研究使用GraphQL来开发我们正在开发的无头CMS版本2。如何使用GraphQL模式进行JSON模式数据验证?

在此CMS的第1版中,我们使用JSON模式在保存到数据库中之前根据模式验证每个文档 - 例如,如果它是博客文章,它将根据Article模式进行验证,并且如果这是一个综合报告(“最佳”列表),它将根据Roundup模式进行验证。

对于版本2,我们正在考虑在API中使用GraphQL。然后,我们发现GraphQL模式基本上与JSON模式平行 - 它描述了文档结构,字段类型等。

所以我们可以简单地拥有“模式真相的一个来源”,即GraphQL模式,并将其用于查询文档并在保存新修订版时验证新文档。 (请注意,我正在讨论如何根据GraphQL模式验证JSON数据,而不是验证针对模式的GraphQL查询。)

我认为数据将根据模式中的所有字段进行验证,因为已弃用的字段除外你只想验证字段的“最新版本”。

我们可以做的三两件事之一:

  1. 使用GraphQL AST直接验证文档,即写数据验证自己。
  2. 使用GraphQL AST生成JSON模式,并使用标准的JSON模式验证器实际验证它。
  3. 只要接受GraphQL不太适合验证,并定义模式两次 - 一次在GraphQL中进行查询,并再次在JSON模式中进行验证(烦人和容易出错以保持同步)。

问题:是#1和#2愚蠢的想法?是否有任何GraphQL工具可以进行这种数据验证?有没有其他方法可以在不定义模式两次的情况下实现这一点?

作为参考,我们的后端将用Python编写,但管理用户界面将是客户端React和JavaScript。这是一个简化版本,我们正在谈论的那种GraphQL架构的(支持“条”和“农达”文档类型):

schema { 
    query: Query 
} 

type Query { 
    documents: [Document!]! 
    document(id: Int): Document! 
} 

interface Document { 
    id: Int! 
    title: String! 
} 

type Article implements Document { 
    id: Int! 
    title: String! 
    featured: Boolean! 
    sections: [ArticleSection!]! 
} 

union ArticleSection = TextSection | PhotoSection | VideoSection 

type TextSection { 
    content: String! 
    heading: String 
} 

type PhotoSection { 
    sourceUrl: String! 
    linkUrl: String 
    caption: String 
    content: String 
} 

type VideoSection { 
    url: String! 
} 

type Roundup implements Document { 
    id: Int! 
    title: String! 
    isAward: Boolean! 
    intro: String 
    hotels: [RoundupHotel!]! 
} 

type RoundupHotel { 
    url: String! 
    photoUrl: String @deprecated(reason: "photoUrl is deprecated; use photos") 
    photos: [RoundupPhoto!]! 
    blurb: String! 
    title: String 
} 

type RoundupPhoto { 
    url: String! 
    caption: String 
} 
+1

你知道https://github.com/jakubfiala/graphql-json-schema吗?我试用了你的graphql模式,基础对我来说很好。 https://runkit.com/fdlk/59baf17d01ac700012e110b4魔鬼可能在细节中。 – flup

+0

是否有你想使用GraphQL的原因?看起来你将会失去很多,因为你有实际的模式验证。 –

回答

1

确定性水平在不断变化的形势

GraphQL是仍然是一种不断发展的技术(as it says right at the top of the spec document),所以可以肯定地说没有真正的“正确”答案。

通则

InputObject类型(“输入”的接口定义语言换算)列表在一起(“[]”中的IDL计算)的各种标量在一起似乎完全覆盖,你可以在JSON做什么。

如果GraphQL的Python实现符合规范,那么将数据作为GraphQL文本或(更好)作为“变量”提供应该提供自定义验证的所有内容:GraphQL验证将做正确的事情。

建议您的具体情况

根据我GraphQL工作至今,我的建议是“随粮”。如果您的GraphQL模式符合您的数据架构要求,只需使用普通的GraphQL验证。如果你作出你自己的验证,它应该在后GraphQL已经做了它的正常的数据形状检查。

总结上述几点,并用一个问题来回答您的问题:让GraphQL处于正常运行状态会导致验证繁重吗?

+0

谢谢。经过深入研究,我认为主要的问题在于输入类型不能包含联合。我们的模式肯定包含了联合,所以我们不能用它作为突变的输入类型(没有黑客)。另请参阅https://github.com/facebook/graphql/issues/114 –

+0

我错了,您可以为每个输入类型输入一个查询(不管是“查询”还是“变异”)? (你会从现有的输入工会自动生成这些)或者你是否说你的请求者不知道它是哪种类型?如果是这样的话,你可以有一个通用的“调度”查询,其输出是一个联合类型? –

+0

我不完全确定你在暗示什么:你的意思是有'updateArticle()'和'updateRoundup()'突变吗?是的,你可以这样做。内部联合仍然是一个问题,比如上面的ArticleSection - 你可以用'ArticleSectionInput'类型为每个类型在联合中使用可空的字段,例如:'textSection','photoSection'和'videoSection'。 ..但它很混乱。 –