#serde-json #json #lodash #serde

serde_json_lodash

lodash.js ported version, work with serde_json::Value

7 releases

0.1.16 Jan 23, 2022
0.1.14 Apr 25, 2021
0.1.1 Dec 26, 2020

#507 in Encoding

43 downloads per month
Used in zero4rs

Custom license

170KB
4.5K SLoC

serde_json_lodash

Documentation build status Downloads

serde_json::Value with lodash.js spec, makes life easier.

Usage

Cargo.toml

[dependencies]
serde_json_lodash = "0.1"

main.rs

#[macro_use] extern crate serde_json_lodash;
use serde_json::json;
fn main() {
  // macro style, optional parameters
  assert_eq!(
    merge!(json!({'a':1}), json!({'b':2}), json!({'c':3})),
    json!({'a': 1, 'b': 2, 'c': 3})
  );

  // fn style, fixed parameters
  use serde_json_lodash::merge;
  assert_eq!(
    merge(json!({'a':1}), json!({'b':2})),
    json!({'a': 1, 'b': 2})
  );

  // `x_`, `_x` helpers for simple types
  assert_eq!(capitalize!(json!("FRED")), json!("Fred"));
  assert_eq!(x_capitalize!("FRED"), json!("Fred"));
  assert_eq!(capitalize_x!(json!("FRED")), "Fred".to_owned());
  assert_eq!(x_capitalize_x!("FRED"), "Fred".to_owned());
}

Concepts

All implements should be same as lodash as possible

How?

  • Every function from lodash.js should be implemented both fn and macro
    • marco is for optional parameters usages
  • The main inputs and return values should be serde_json::Value, excepts:
    • Inputs:
      • If the input parameters are options, not data, always using primitive type instead Value
        • e.q. _.chunk(array, [size=1]) => ::chunk(json!([1,2,3]), 2), size should be usize, not Value::Number
      • Some cases we use std::ops::Fn as input parameter
        • e.q. _.findIndex(array, predicate, ...) => ::find_index(..., predicate: fn(&Value) -> bool, ...)
    • Retune values:
      • If return value is statistic, using primitive type instead Value
        • e.q. _.findIndex(...) => ::find_index(...) -> isize, return value should be isize, not Value::Number
      • Because there is no undefined type in serde_json, so if the original function return undefined, the ported version should return Value::Null
  • If the original function allows optional parameters:
    • known amount, then the ported fn should should be as required
      • e.q. _.get(object, path, [defaultValue]) => ::get(object, path, defaultValue)
    • infinity amount, the ported fn should only keep one, and no more optionals
      • e.q. _.merge(object, [...sources]) => ::merge(object, source), but macro could ::merge!(object, source1, source2, ...)
  • It might implement helper functions, for different input and output types:
    • with x_ prefix: input is not Value, will be downgrade type
      • e.q. x_capitalize(&str) -> Value
    • with _x suffix: output is not Value, will be downgrade type
      • e.q. capitalize_x(Value) -> String
    • with both x_ and _x
      • e.q. x_capitalize_x(&str) -> &str, x_add_x(n: Number, n2: Number) -> Number
    • If the function accept multiple types, the helper functions will only choose one type to implement
      • e.q. _.toString([1,2]), _.toString(123) => ::x_to_string(v: &str) -> Value
  • About the test cases:
    • Examples: section should be exactly same as the examples in lodash doc.
    • More test cases should all be put in the More examples section, we relied on powerful rust's doc test

Dev memo

# Up
./dev.sh

# Watch and test single file
./dev.sh --doc set

# Lint
./lint.sh

# Preview doc
cargo doc --open

# Bump patch version and push
./bump_push.sh

Check lodash.js api

$ npm i
$ node
Welcome to Node.js v15.14.0.
Type ".help" for more information.
> const l = require('lodash')
undefined
> l.toString()
''
>

Dependencies

~0.5–1MB
~20K SLoC