#restful #fields #parser #filter #api #guideline #zalando

z157

Parser for fields filtering according to Zalando's RESTful API guideline #157

7 releases

new 0.3.1 Dec 21, 2024
0.3.0 Dec 21, 2024
0.2.1 Dec 21, 2024
0.1.2 Dec 20, 2024
0.0.3 Dec 19, 2024

#261 in HTTP server

Download history 331/week @ 2024-12-14

331 downloads per month

MIT/Apache

23KB
420 lines

z157

Crates.io docs.rs (with version)

Parser for the field filter defined in Zalando's RESTful API and Event guideline #157.

When would I need this?

If your HTTP service accepts a query parameter that lets the caller specify which fields they would like, this crate helps you parse such a string.

GET http://localhost/users/0001?fields=(age,address(street,city))

The value of the fields query parameter is parsed into a tree of field names.

Example

use z157::Tree;

fn main() {
    // Select fields to include
    let tree = Tree::parse("(name,bio(height(meters,centimeters),age))").unwrap();
    
    assert!(!tree.negation());
    let height = tree.index(&["bio", "height"]).unwrap();
    assert!(height.children().any(|field| field.name() == "meters"));
    assert!(height.children().any(|field| field.name() == "centimeters"));
    
    for field in tree.walk() {
        // z157::Field::path returns a vector of ancestors from the top-level
        // field name until and including itself.
        println!("{}", field.path().join("."));
        // This would print out:
        // name
        // bio
        // bio.height
        // bio.height.meters
        // bio.height.centimeters
        // bio.age
    }
    
    // Select fields to exclude
    let tree = Tree::parse("-(bio)").unwrap();
    
    assert!(tree.negation());
}

The field filter specification

<fields>            ::= [ <negation> ] <fields_struct>
<fields_struct>     ::= "(" <field_items> ")"
<field_items>       ::= <field> [ "," <field_items> ]
<field>             ::= <field_name> | <fields_substruct>
<fields_substruct>  ::= <field_name> <fields_struct>
<field_name>        ::= <dash_letter_digit> [ <field_name> ]
<dash_letter_digit> ::= <dash> | <letter> | <digit>
<dash>              ::= "-" | "_"
<letter>            ::= "A" | ... | "Z" | "a" | ... | "z"
<digit>             ::= "0" | ... | "9"
<negation>          ::= "!"

Dependencies

~1MB
~17K SLoC