Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

RedisJSON/jsonpath

Open more actions menu
 
 

Repository files navigation

jsonpath_lib

Build Status crates.io npm Codecov

Rust 버전 JsonPath 구현으로 WebassemblyJavascript에서도 유사한 API 인터페이스를 제공 한다.

It is JsonPath JsonPath engine written in Rust. it provide a similar API interface in Webassembly and Javascript too.

Rust API

jsonpath_lib crate

Go to jsonpath_lib creates.io

extern crate jsonpath_lib as jsonpath;
Rust - jsonpath::Selector struct
#[derive(Deserialize, PartialEq, Debug)]
struct Friend {
    name: String,
    age: Option<u8>,
}

let json_obj = json!({
    "school": {
        "friends": [
            {"name": "친구1", "age": 20},
            {"name": "친구2", "age": 20}
        ]
    },
    "friends": [
        {"name": "친구3", "age": 30},
        {"name": "친구4"}
]});

let mut selector = Selector::new();

let result = selector
    .path("$..[?(@.age >= 30)]").unwrap()
    .value(&json_obj)
    .select().unwrap();

assert_eq!(vec![&json!({"name": "친구3", "age": 30})], result);

let result = selector.select_as_str().unwrap();
assert_eq!(r#"[{"name":"친구3","age":30}]"#, result);

let result = selector.select_as::<Friend>().unwrap();
assert_eq!(vec![Friend { name: "친구3".to_string(), age: Some(30) }], result);
Rust - jsonpath::SelectorMut struct
let json_obj = json!({
    "school": {
        "friends": [
            {"name": "친구1", "age": 20},
            {"name": "친구2", "age": 20}
        ]
    },
    "friends": [
        {"name": "친구3", "age": 30},
        {"name": "친구4"}
]});

let mut selector_mut = SelectorMut::new();

let result = selector_mut
    .str_path("$..[?(@.age == 20)].age").unwrap()
    .value(json_obj)
    .replace_with(&mut |v| {
        let age = if let Value::Number(n) = v {
            n.as_u64().unwrap() * 2
        } else {
            0
        };

        Some(json!(age))
    }).unwrap()
    .take().unwrap();

assert_eq!(result, json!({
    "school": {
        "friends": [
            {"name": "친구1", "age": 40},
            {"name": "친구2", "age": 40}
        ]
    },
    "friends": [
        {"name": "친구3", "age": 30},
        {"name": "친구4"}
]}));
Rust - jsonpath::select(json: &serde_json::value::Value, jsonpath: &str)
let json_obj = json!({
    "school": {
        "friends": [
            {"name": "친구1", "age": 20},
            {"name": "친구2", "age": 20}
        ]
    },
    "friends": [
        {"name": "친구3", "age": 30},
        {"name": "친구4"}
]});

let json = jsonpath::select(&json_obj, "$..friends[0]").unwrap();

assert_eq!(json, vec![
    &json!({"name": "친구3", "age": 30}),
    &json!({"name": "친구1", "age": 20})
]);
Rust - jsonpath::select_as_str(json_str: &str, jsonpath: &str)
let ret = jsonpath::select_as_str(r#"
{
    "school": {
        "friends": [
                {"name": "친구1", "age": 20},
                {"name": "친구2", "age": 20}
            ]
    },
    "friends": [
        {"name": "친구3", "age": 30},
        {"name": "친구4"}
    ]
}
"#, "$..friends[0]").unwrap();

assert_eq!(ret, r#"[{"name":"친구3","age":30},{"name":"친구1","age":20}]"#);
Rust - jsonpath::select_as<T: `serde::de::DeserializeOwned`>(json_str: &str, jsonpath: &str)
#[derive(Deserialize, PartialEq, Debug)]
struct Person {
    name: String,
    age: u8,
    phones: Vec<String>,
}

let ret: Vec<Person> = jsonpath::select_as(r#"
{
    "person":
        {
            "name": "Doe John",
            "age": 44,
            "phones": [
                "+44 1234567",
                "+44 2345678"
            ]
        }
}
"#, "$.person").unwrap();

let person = Person {
    name: "Doe John".to_string(),
    age: 44,
    phones: vec!["+44 1234567".to_string(), "+44 2345678".to_string()],
};

assert_eq!(ret[0], person);
Rust - jsonpath::PathCompiled::compile(jsonpath: &str)
let template = jsonpath::PathCompiled::compile("$..friends[0]").unwrap();

let json_obj = json!({
    "school": {
        "friends": [
            {"name": "친구1", "age": 20},
            {"name": "친구2", "age": 20}
        ]
    },
    "friends": [
        {"name": "친구3", "age": 30},
        {"name": "친구4"}
]});

let json = template.select(&json_obj).unwrap();

assert_eq!(json, vec![
    &json!({"name": "친구3", "age": 30}),
    &json!({"name": "친구1", "age": 20})
]);
Rust - jsonpath::selector(json: &serde_json::value::Value)
let json_obj = json!({
    "school": {
        "friends": [
            {"name": "친구1", "age": 20},
            {"name": "친구2", "age": 20}
        ]
    },
    "friends": [
        {"name": "친구3", "age": 30},
        {"name": "친구4"}
]});

let mut selector = jsonpath::selector(&json_obj);

let json = selector("$..friends[0]").unwrap();

assert_eq!(json, vec![
    &json!({"name": "친구3", "age": 30}),
    &json!({"name": "친구1", "age": 20})
]);

let json = selector("$..friends[1]").unwrap();

assert_eq!(json, vec![
    &json!({"name": "친구4"}),
    &json!({"name": "친구2", "age": 20})
]);
Rust - jsonpath::selector_as<T: serde::de::DeserializeOwned>(json: &serde_json::value::Value)
let json_obj = json!({
    "school": {
       "friends": [
            {"name": "친구1", "age": 20},
            {"name": "친구2", "age": 20}
        ]
    },
    "friends": [
        {"name": "친구3", "age": 30},
        {"name": "친구4"}
]});

#[derive(Deserialize, PartialEq, Debug)]
struct Friend {
    name: String,
    age: Option<u8>,
}

let mut selector = jsonpath::selector_as::<Friend>(&json_obj);

let json = selector("$..friends[0]").unwrap();

let ret = vec!(
    Friend { name: "친구3".to_string(), age: Some(30) },
    Friend { name: "친구1".to_string(), age: Some(20) }
);
assert_eq!(json, ret);

let json = selector("$..friends[1]").unwrap();

let ret = vec!(
    Friend { name: "친구4".to_string(), age: None },
    Friend { name: "친구2".to_string(), age: Some(20) }
);

assert_eq!(json, ret);
Rust - jsonpath::delete(value: &Value, path: &str)
let json_obj = json!({
    "school": {
        "friends": [
            {"name": "친구1", "age": 20},
            {"name": "친구2", "age": 20}
        ]
    },
    "friends": [
        {"name": "친구3", "age": 30},
        {"name": "친구4"}
]});

let ret = jsonpath::delete(json_obj, "$..[?(20 == @.age)]").unwrap();

assert_eq!(ret, json!({
    "school": {
        "friends": [
            null,
            null
        ]
    },
    "friends": [
        {"name": "친구3", "age": 30},
        {"name": "친구4"}
]}));
Rust - jsonpath::replace_with<F: FnMut(&Value) -> Value>(value: &Value, path: &str, fun: &mut F)
let json_obj = json!({
    "school": {
        "friends": [
            {"name": "친구1", "age": 20},
            {"name": "친구2", "age": 20}
        ]
    },
    "friends": [
        {"name": "친구3", "age": 30},
        {"name": "친구4"}
]});

let ret = jsonpath::replace_with(json_obj, "$..[?(@.age == 20)].age", &mut |v| {
    let age = if let Value::Number(n) = v {
        n.as_u64().unwrap() * 2
    } else {
        0
    };

    Some(json!(age))
}).unwrap();

assert_eq!(ret, json!({
    "school": {
        "friends": [
            {"name": "친구1", "age": 40},
            {"name": "친구2", "age": 40}
        ]
    },
    "friends": [
        {"name": "친구3", "age": 30},
        {"name": "친구4"}
]}));

Rust - Other Examples

Javascript API

npm package
jsonpath-wasm

Goto jsonpath-wasm npmjs.org

// browser
import * as jsonpath from "jsonpath-wasm";
// NodeJs
const jsonpath = require('jsonpath-wasm');
jsonpath-wasm

wasm-bindgen 리턴 타입 제약 때문에 빌더 패턴은 지원하지 않는다.

It does not support builder-pattern due to the return type restriction of wasm-bindgen.

let jsonObj = {
    "school": {
        "friends": [
            {"name": "친구1", "age": 20},
            {"name": "친구2", "age": 20}
        ]
    },
    "friends": [
        {"name": "친구3", "age": 30},
        {"name": "친구4"}
    ]
};

let ret = [
    {"name": "친구3", "age": 30},
    {"name": "친구1", "age": 20}
];

let selector = new jsonpath.Selector();
selector.path('$..friends[0]');
selector.value(jsonObj);

let retObj = selector.select();

console.log(JSON.stringify(ret) == JSON.stringify(retObj));

// => true

빌더 패턴 제약은 Selector class와 동일하다.

let jsonObj = {
    'school': {
        'friends': [
            {'name': '친구1', 'age': 20},
            {'name': '친구2', 'age': 20},
        ],
    },
    'friends': [
        {'name': '친구3', 'age': 30},
        {'name': '친구4'},
    ],
};

let selector = new jsonpath.SelectorMut();
selector.path('$..[?(@.age == 20)]');

{
    selector.value(jsonObj);
    selector.deleteValue();

    let resultObj = {
        'school': {'friends': [null, null]},
        'friends': [
            {'name': '친구3', 'age': 30},
            {'name': '친구4'},
        ],
    };
    console.log(JSON.stringify(selector.take()) !== JSON.stringify(resultObj));
    
    // => true
}

{
    selector.value(jsonObj);
    selector.replaceWith((v) => {
        v.age = v.age * 2;
        return v;
    });

    let resultObj = {
        'school': {
            'friends': [
                {'name': '친구1', 'age': 40},
                {'name': '친구2', 'age': 40},
            ],
        },
        'friends': [
            {'name': '친구3', 'age': 30},
            {'name': '친구4'},
        ],
    };
    console.log(JSON.stringify(selector.take()) !== JSON.stringify(resultObj));
    
    // => true
}
Javascript - jsonpath.select(json: string|object, jsonpath: string)
let jsonObj = {
    "school": {
        "friends": [
            {"name": "친구1", "age": 20},
            {"name": "친구2", "age": 20}
        ]
    },
    "friends": [
        {"name": "친구3", "age": 30},
        {"name": "친구4"}
    ]
};

let ret = [
    {"name": "친구3", "age": 30},
    {"name": "친구1", "age": 20}
];


let selectAsString = jsonpath.select(JSON.stringify(jsonObj), '$..friends[0]');
let selectAsObj = jsonpath.select(jsonObj, '$..friends[0]');

console.log(
    JSON.stringify(ret) == JSON.stringify(selectAsString),
    JSON.stringify(ret) == JSON.stringify(selectAsObj)
);

// => true, true
Javascript - jsonpath.compile(jsonpath: string)
let error = jsonpath.compile('');
console.log(typeof error, error); //string 'path error'

let template = jsonpath.compile('$..friends[0]');

let jsonObj = {
    "school": {
        "friends": [
            {"name": "친구1", "age": 20},
            {"name": "친구2", "age": 20}
        ]
    },
    "friends": [
        {"name": "친구3", "age": 30},
        {"name": "친구4"}
    ]
};

let ret = [
    {"name": "친구3", "age": 30},
    {"name": "친구1", "age": 20}
];

let selectAsString = template(JSON.stringify(jsonObj));
let selectAsObj = template(jsonObj);

console.log(
    JSON.stringify(ret) == JSON.stringify(selectAsString),
    JSON.stringify(ret) == JSON.stringify(selectAsObj)
);

// => true, true

let jsonObj2 = {
    "school": {
        "friends": [
            {"name": "Millicent Norman"},
            {"name": "Vincent Cannon"}
        ]
    },
    "friends": [ {"age": 30}, {"age": 40} ]
};

let ret2 = [
    {"age": 30},
    {"name": "Millicent Norman"}
];

let selectAsString2 = template(JSON.stringify(jsonObj2));
let selectAsObj2 = template(jsonObj2);

console.log(
        JSON.stringify(ret2) == JSON.stringify(selectAsString2),
        JSON.stringify(ret2) == JSON.stringify(selectAsObj2)
);

// => true, true
Javascript - jsonpath.selector(json: string|object)
let jsonObj = {
    "school": {
        "friends": [
            {"name": "친구1", "age": 20},
            {"name": "친구2", "age": 20}
        ]
    },
    "friends": [
        {"name": "친구3", "age": 30},
        {"name": "친구4"}
    ]
};

let ret1 = [
    {"name": "친구3", "age": 30},
    {"name": "친구1", "age": 20}
];

let ret2 = [
    {"name": "친구4"},
    {"name": "친구2", "age": 20}
];

let selector = jsonpath.selector(jsonObj);
// or as json string 
// let selector = jsonpath.selector(JSON.stringify(jsonObj));

let select1 = selector('$..friends[0]');
let select2 = selector('$..friends[1]');

console.log(
    JSON.stringify(ret1) == JSON.stringify(select1),
    JSON.stringify(ret2) == JSON.stringify(select2)
);

// => true, true
Javascript - jsonpath.deleteValue(json: string|object, path: string)
let jsonObj = {
    "school": {
        "friends": [
            {"name": "친구1", "age": 20},
            {"name": "친구2", "age": 20}
        ]
    },
    "friends": [
        {"name": "친구3", "age": 30},
        {"name": "친구4"}
    ]
};

let _1 = jsonpath.deleteValue(jsonObj, '$..friends[0]');
let result = jsonpath.deleteValue(_1, '$..friends[1]');

console.log(JSON.stringify(result) !== JSON.stringify({
    "school": { "friends": [null, null]},
    "friends": [null, null]
}));

// => true
Javascript - jsonpath.replaceWith(json: string|object, path: string, fun: function(json: object) => json: object
let jsonObj = {
    "school": {
        "friends": [
            {"name": "친구1", "age": 20},
            {"name": "친구2", "age": 20}
        ]
    },
    "friends": [
        {"name": "친구3", "age": 30},
        {"name": "친구4"}
    ]
};

let result = jsonpath.replaceWith(jsonObj, '$..friends[0]', (v) => {
    v.age = v.age * 2;
    return v;
});

console.log(JSON.stringify(result) === JSON.stringify({
    "school": {
        "friends": [
            {"name": "친구1", "age": 40},
            {"name": "친구2", "age": 20}
        ]
    },
    "friends": [
        {"name": "친구3", "age": 60},
        {"name": "친구4"}
    ]
}));

// => true

Javascript - Other Examples

About

JsonPath engine written in Rust. Webassembly and Javascript support too

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Rust 85.7%
  • JavaScript 10.1%
  • HTML 2.0%
  • Shell 1.7%
  • Lua 0.5%
Morty Proxy This is a proxified and sanitized view of the page, visit original site.