Home

Awesome

JSON Formatter Smartmodule

SmartModule to read values from JSON records, generate a user-define formatted string, and update the record. This SmartModule is map type, where each record-in generates a new records-out.

Input Records

Each row is an individual JSON record:

{
  "email": "alice@acme.com",
  "name": "Alice Liddell",
  "type": "subscribe",
  "source": "front-page"
}
{
  "email": "bob@acme.com",
  "name": "Bob Newland",
  "type": "use-case",
  "source": "iot",
  "description": "Tracking fleet of trucks"
}
{
  "email": "charlie@acme.com",
  "name": "Charlie Brimmer",
  "type": "use-case",
  "source": "clickstream",
  "description": "Track user interests"
}
{
  "email": "random@acme.com",
  "name": "Random Dude",
  "type": "undefined"
}

Transformation spec

The transformation spec covers 2 cases:

The default formatter is required and can be used with or without the match section. If used together, the matching statement is checked first, and default is applied if no matching record is found.

In this example, we'll use the following transformation spec:

spec:
  match:
    - key: "/type"
      value: "subscribe"
      format:
        with: ":loudspeaker: {} ({}) subscribed on {}"
        using: 
          - "/name"
          - "/email"
          - "/source"
        output: "/formatted"
    - key: "/type"
      value: "use-case"
      format:
        with: ":confetti_ball: {} ({}) wants to solve the following '{}' use-case:\n>{}"
        using: 
          - "/name"
          - "/email"
          - "/source"
          - "/description"
        output: "/formatted"
  default:
    format: 
      with: "{} ({}) submitted a request"
      using: 
        - "/name"
        - "/email"
      output: "/formatted"

NOTE: The JSON object references for look-up and output must be in JSON Pointer notation.

Output Records

JSON records augmented with formatted strings:

{
  "email": "alice@acme.com",
  "formatted": ":loudspeaker: Alice Liddell (alice@acme.com) subscribed on front-page",
  "name": "Alice Liddell",
  "source": "front-page",
  "type": "subscribe"
}
{
  "description": "Tracking fleet of trucks",
  "email": "bob@acme.com",
  "formatted": ":confetti_ball: Bob Newland (bob@acme.com) wants to solve the following 'iot' use-case:\n>Tracking fleet of trucks",
  "name": "Bob Newland",
  "source": "iot",
  "type": "use-case"
}
{
  "description": "Track user interests",
  "email": "charlie@acme.com",
  "formatted": ":confetti_ball: Charlie Brimmer (charlie@acme.com) wants to solve the following 'clickstream' use-case:\n>Track user interests",
  "name": "Charlie Brimmer",
  "source": "clickstream",
  "type": "use-case"
}
{
  "email": "random@acme.com",
  "formatted": "Random Dude (random@acme.com) submitted a request",
  "name": "Random Dude",
  "type": "undefined"
}

Build binary

Use smdk command tools to build:

smdk build

Inline Test

Use smdk to test:

smdk test --file ./test-data/input.txt -e spec='{ "match": [ { "key": "/type", "value": "subscribe", "format": { "with": ":loudspeaker: {} ({}) subscribed on {}", "using": [ "/name", "/email", "/source" ], "output": "/formatted" } }, { "key": "/type", "value": "use-case", "format": { "with": ":confetti_ball: {} ({}) wants to solve the following '{}' use-case:\n>{}", "using": [ "/name", "/email", "/source", "/description" ], "output": "/formatted" } } ], "default": { "format": { "with": "{} ({}) submitted a request", "using": [ "/name", "/email" ], "output": "/formatted" } } }'

Cluster Test

Use smdk to load the startmodule to a fluvio cluster:

smdk load 

Test using transform.yaml file:

smdk test --file ./test-data/input.txt  --transforms-file ./test-data/transform.yaml

A second default-only transforms-default.yaml file is also available:

smdk test --file ./test-data/input.txt  --transforms-file ./test-data/transform-default.yaml

NOTE: Changing the parameters inside the transforms files yield different results.

Cargo Compatible

The project has tests that can be run using cargo:

cargo build
cargo test