Skip to content

johnholdun/json-transformer

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

12 Commits
 
 
 
 
 
 

Repository files navigation

JSON Transformer

This is a proof-of-concept for a means of transforming JSON that may become a full-fledged spec someday. It's like XSLT, but for JSON!

A transformation requires two JSON documents: an input document and a rules document. The input document is the source of your data, and the rules document describes how to transform your data to return the desired output. Your input and your rules must both be valid JSON objects.

A rules document is designed to resemble the desired output; a simple rules document applied to any source may simply return your rules document. For example, this is a valid rules document that is not affected by an input document; running this rules document through the transformer will simply return itself, regardless of your input:

{ "hello": "world" }

Strings in your rules document can take the form of a JSON Path, in which case they will be replaced with whatever data exists at the specified path in your input document:

// input
{ "message": "Hello world" }

// rules
{ "foobar": "$.message" }

// output
{ "foobar": "Hello world" }

You can also create repeating objects by adding a special $each key to an object in your rules document. The value of an $each key should be a JSON Path pointing to an array or object in your input document. The $each key's parent object will then be repeated once for each member of the array or object found, creating an object whose keys match the keys that are siblings of your $each key. (The $each key will not be preserved in your output document). If any of the $each key's sibling's values are JSON Paths, they will be evaluated relative to the current item from the array or object being used to generate your result.

// input
{
  "items": [
    { "type": "a", "id": 1 },
    { "type": "b", "id": 2 },
    { "type": "c", "id": 3 }
  ]
}

// rules
{
  "result": {
    "$each": "$.items",
    "kind": "$.type",
    "id": "$.id"
  }
}

// output
{
  "result": [
    { "kind": "a", "id": 1 },
    { "kind": "b", "id": 2 },
    { "kind": "c", "id": 3 }
  ]
}

If you want to use your input data to determine the order of the items in your output data, include an $index key alongside your $each key. (Like with $each, this key will not be included in your output.)

// input
{
  "vegetables": [
    { "name": "artichokes", "position": 3 },
    { "name": "brussels sprouts", "position": 1 },
    { "name": "carrots", "position": 2 }
  ]
}

// rules
{
  "result": {
    "$each": "$.vegetables",
    "$index": "$.position",
    "name": "$.name"
  }
}

// output
{
  "result": [
    { "name": "brussels sprouts" },
    { "name": "carrots" },
    { "name": "artichokes" }
  ]
}

Interested in returning an object instead of an array? Specify a $key instead of an $index. (Again, $key will be omitted from your result.)

// input
{
  "staff": [
    { "name": "Daisy", "role": "Director" },
    { "name": "Minnie", "role": "Principal" },
    { "name": "Clarabelle", "role": "Lead" }
  ]
}

// rules
{
  "result": {
    "$each": "$.staff",
    "$key": "$.role",
    "name": "$.name"
  }
}

// output
{
  "result": {
    "Director": { "name": "Daisy" },
    "Principal": { "name": "Minnie" },
    "Lead": { "name": "Clarabelle" }
  }
}

Interested in returning something other than an object from your $each calculation? If you include a $value key, that's what will be returned instead—either as the value of your object if you specify a $key, or as an item in an array.

// input
{
  "staff": [
    { "name": "Daisy", "role": "Director" },
    { "name": "Minnie", "role": "Principal" },
    { "name": "Clarabelle", "role": "Lead" }
  ]
}

// rules
{
  "result": {
    "$each": "$.staff",
    "$key": "$.role",
    "$value": "$.name"
  }
}

// output
{
  "result": {
    "Director": "Daisy",
    "Principal": "Minnie",
    "Lead": "Clarabelle"
  }
}

Your $each key's path can also include wildcards! These will be expanded so that your resulting object contains all possible values from your input doc, and you can use your wildcard value in each item as well using a named capture.

// input
{
  "silverware": {
    "forks": [
      {
        "skuId": "7fdd8",
        "quality": "good"
      }
    ],
    "spoons": [
      {
        "skuId": "ca733",
        "quality": "great"
      }
    ],
    "knives": [
      {
        "skuId": "94033",
        "quality": "knifey"
      }
    ]
  }
}

// rules
{
  "data": {
    "$each": "$.silverware.:type",
    "id": "$.skuId",
    "type": ":type",
    "quality": "$.quality"
  }
}

// output
{
  "data": [
    {
      "id": "7fdd8",
      "type": "forks",
      "quality": "good"
    },
    {
      "id": "ca733",
      "type": "spoons",
      "quality": "great"
    },
    {
    {
      "id": "94033",
      "type": "knives",
      "quality": "knifey"
    }
  ]
}

About

Use JSON to turn JSON into JSON

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages