2014-03-07 103 views
0

我們正在嘗試爲我們的REST服務構建資源擴展功能。資源擴張可通過以下方式解析REST服務的資源擴展

 

    fields=field1,field2(sf1,sf2),field3[Format],field4(sf1,sf2,sf3) 

什麼能解析這個最好的方式來提供?解析必須發生在每個傳入的請求上,因此,必須是更好的表現。

我們試圖檢查是否可以爲此定義正則表達式。什麼可能是這種模式的正則表達式?

編輯(10-MAR-2014):字符串只包含元數據(Java字段名),它可以同時多層次樣

field1(sf1,sf2(sf21,sf22)),field2[Format],field3[Format],field4(sf1,sf2,sf3) 

我應該使用正則表達式或手動解析?

回答

0

如果不知道每個字段的數據值,試圖找出特定的RegEx可能會非常困難。

爲什麼不使用POST或PUT並將數據值放在消息正文中?這樣,您可以使用JSON來組織數據。 (OK ... XML或YAML也可以工作 - 但我喜歡JSON)。

+0

基本上這是我們正在關注/構建的服務模型。這種模式會出現在ACCEPT標頭中,我們會解析它。這些名稱是Java字段名稱,因此您可以假設Java允許用於命名字段的字符在此處適用。 – Niranjan

+0

根據我的經驗,在頭文件中交易數據是不好的,特別是如果你必須解析這些信息。但是,如果您必須這樣做,請使用標準__?__標記來分隔查詢段/字段。如果你不把自己限制在能夠提供的數據上,並且如果有人(錯誤或其他)傳遞逗號,字母或括號字符,查詢就會非常容易中斷。 – epluribusunix

+0

嗨,我想我沒有正確闡述。這將不包含任何數據,這些字段只是元數據(如字段名稱)。而且,它將只包含元數據。 – Niranjan

1

正則表達式不支持嵌套/平衡語法。例如,解析數學語句並確保每個左括號具有適當平衡的右括號,或解析XML或HTML以確保每個元素都被正確關閉,都需要更具表達性的語法。 (有關學術解釋,請參閱Chomsky's Hierarchy,特別關注常規語言和上下文無關語言之間的區別)。

爲了使用嵌套語法解析語言,您需要相當於'Push Down Automata'( PDA),但不要害怕 - 所有這些奇特的術語實際上都是微不足道的。您可以使用遞歸或循環,在每次迭代中使用正則表達式來解決問題,或者簡單地構建自己的解析方法。

我最近實施完全相同的功能,在我們的REST API,雖然我的語法略有不同,我懷疑你會發現這段代碼有幫助:

/** 
* Given a single packed string that defines a recursive set of fields, 
* this will parse and return a Map of terms from the root level where the 
* term is mapped to the packed string defining the sub-fields within that key. 
* 
* Assume the primary/root result is a Movie... 
*    --(raw==null) get all movie First Order (FO) attributes 
* stars  --get all movie FO, and expand stars relation 
* title  --get movies FO id and title 
* title,stars --get movies FO id and title, and expand stars relation 
* 
* stars{}  --get all movie FO, and expand stars relation (same as stars) 
* stars{name} --get all movie FO, and expand stars relation getting star FO id and name 
* stars{contractStudio} --get all movie FO, expand stars relation getting all star FO and expand stars contract studio 
* stars{name,contractStudio} --get all movie FO, and expand stars relation getting star FO id and name and expand stars contract studio 
* title,stars{name,contractStudio{name,founded}} --get movies FO id and title, and expand stars relation getting star FO id and name and expand stars contract studio with the studio FO name and founded date 
*/ 
private Map<String, String> parseRequestParameter(String raw) { 
    if (raw == null || raw.isEmpty()) return Collections.emptyMap(); 
    Map<String, String> results = new HashMap<>(); 
    int i = 0; 
    int j = 0; 
    while (j < raw.length()) { 
     char c = raw.charAt(j); 
     //move j to end of attr name 
     while (c != '{' && c != ',' && ++j < raw.length()) {c = raw.charAt(j);} 
     String attr = raw.substring(i, i = j).trim(); 
     if (!attr.isEmpty()) { 
      //capture the optional sub-expansion 
      if (c == '{') { 
       i++; //move i past the opening '{' 
       int pDepth = 1; 
       while (pDepth > 0 && ++j < raw.length()) { //pDepth is depth of nested { } 
        pDepth += (c = raw.charAt(j)) == '{' ? 1 : (c == '}' ? -1 : 0); 
       } 
       results.put(attr, raw.substring(i, j).trim()); 
       if (++j < raw.length()) c = raw.charAt(i = j); //move i and c past the closing '}' 
      } 
      else { 
       results.put(attr, null); 
      } 
     } 
     //skip any unexpected suffix trash... only ',' marks next term. 
     while ((i = ++j) < raw.length() && c != ',') {c = raw.charAt(j);} 
    } 
    return results; 
} 

在我們的情況下,你可能從推斷javadoc,如果沒有指定擴展字符串,我們返回結果的所有'first order'(FO)屬性。如果指定了特定屬性,則它們是擴展術語(如果它們命名可擴展的關係屬性)或縮小術語(如果它們命名FO屬性)。如果指定了縮小術語,則呈現的結果包含只有要求的條款。此外,無論所要求的條款是什麼,我們都會返回該ID。

上面的方法只解析包含擴展規範的原始值。它生成一個Map,其中關鍵字是擴展規範頂層的一個單詞。這些值是擴展規格(剩餘打包),您需要在擴展時適用於該術語。這是迴歸發揮的地方。顯然,這發生在比這個方法更高的層次上,我假設你可以從這裏到達那裏。

該方法相當健壯。它假定原始值可能包含不平衡的花括號和垃圾字符。遇到這些情況時,它們會忽略它們,並儘可能地從原始價值中拯救。這是'最後失敗'的方法。