2017-08-30 103 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'。 ..但它很混亂。 –