Theodor Golo Hillmann
Theodor Golo Hillmann

Reputation: 53

Convert JSON to YAML with reference properties

I am building a web interface for configuring YAML files and therefore need to parse YAML to JSON and back to YAML. The node-module yaml-js does quite a good job converting my YAML to JSON but when I convert back to YAML the files end up huge and not really human-readable as duplicates are not saved as anchors and references. Am I doing something wrong?

Here is a minimal version of what I would like to achieve:

const yaml = require("js-yaml");

const json = {
  constants: {
    person: {
      name: "july",
      id: 2
    }
  },
  worldObject: {
    name: "july",
    id: 2
  },
  worldArray: [
    {
      name: "july",
      id: 2
    },
    {
      name: "july",
      id: 2
    }
  ]
};

const jsonToYaml = async () => {
  const output = yaml.safeDump(json);
  console.log(output);
};

jsonToYaml();

Expected output

constants:
    person: &person 
        name: july
    id: 2
worldObject: *person
worldArray:
- *person
- *person

Alternative: https://codesandbox.io/s/small-pine-0w4ze?file=/src/index.js

Huge thanks in advance! Theo

Upvotes: 3

Views: 3967

Answers (1)

Mr. Polywhirl
Mr. Polywhirl

Reputation: 48630

In your example, the source JavaScript object (not JSON) has no concept of references. You are not converting a JavaScript object with nested references. You can only make use of YAML reference as long as your underlying JavaScript object has references.

Here is an example that provides your expected output:

const yaml = require("js-yaml");

const person = {
  name: "july",
  id: 2
};

const obj = {
  constants: {
    person: person
  },
  worldObject: person,
  worldArray: [
    person,
    person
  ]
};

const jsonToYaml = async () => {
  const output = yaml.safeDump(obj);
  console.log(output);
};

jsonToYaml();

Output

constants:
  person: &ref_0
    name: july
    id: 2
worldObject: *ref_0
worldArray:
  - *ref_0
  - *ref_0

You lose the concept of references, when moving strictly from JSON to YAML.

For the expanded object, you can pass true for noRefs.

const output = yaml.safeDump(obj, { noRefs: true });

An actual JSON example

As you can see in the example below, I am using actual JSON. As described above, once you deserialize the JSON into an object, you actually have no references.

const yaml = require("js-yaml");

const jsonStr = `{
  "constants": {
    "person": {
      "name": "july",
      "id": 2
    }
  },
  "worldObject": {
    "name": "july",
    "id": 2
  },
  "worldArray": [ {
    "name": "july",
    "id": 2
  }, {
    "name": "july",
    "id": 2
  } ]
}`;

const jsonToYaml = async () => {
  console.log(yaml.safeDump(JSON.parse(jsonStr)));
};

jsonToYaml();

Upvotes: 1

Related Questions