2014-03-07 81 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,其中关键字是扩展规范顶层的一个单词。这些值是扩展规格(剩余打包),您需要在扩展时适用于该术语。这是回归发挥的地方。显然,这发生在比这个方法更高的层次上,我假设你可以从这里到达那里。

该方法相当健壮。它假定原始值可能包含不平衡的花括号和垃圾字符。遇到这些情况时,它们会忽略它们,并尽可能地从原始价值中拯救。这是'最后失败'的方法。