Skip to content

Instantly share code, notes, and snippets.

@coolaj86
Last active March 14, 2022 04:32
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save coolaj86/59fea91e1b2ecba711820c5c6d8528c4 to your computer and use it in GitHub Desktop.
Save coolaj86/59fea91e1b2ecba711820c5c6d8528c4 to your computer and use it in GitHub Desktop.
"Can you write code?" litmus test.

The Developer Litmus Test

I used to think that fizzbuzz was a stupid way to test if someone is a developer.

Screen Shot 2022-01-24 at 3 06 33 AM

Now I think that it's a good litmus test.

However, I think I've found a better one...

Can you convert JSON to YAML?

My Expectation

My expectation is that a mid-senior level developer should be able to:

  • write this in 30-60 minutes
  • debug / fine tune within another 60 minutes
  • publish within another 60 minutes
  • take another 60 minutes for leeway

If a developer cannot solve this problem within 2 days - because maybe they need a break to clear their head after overthinking it, or they've never had to work independently before - then I don't think they're a good hire for jobs that require any sort of data or API manipulation.

Problem Description

Given JSON that looks like this:

var data = {
  foo: [
    {
      bar: [
        {
          baz: ["apples", "bananas"],
        },
      ],
      quux: [
        {
          do: ["red thing", "blue thing"],
        },
      ],
    },
  ],
  grault: {
    name: "Bob",
    age: 37,
    grumpy: false,
    nullish: null,
  },
  answer: 42,
};

Can you produce a function that outputs it as YAML?

foo:
  - bar:
      - baz:
          - "apples"
          - "bananas"
    quux:
      - do:
          - "red thing"
          - "blue thing"
empty: []
grault:
  name: "Bob"
  age: 37
  grumpy: false
  nullish: null
silly: {}
answer: 42

The conversion is 1:1. This is just testing that you know how to use basic Object and Array methods, and keep track of state.

The solution could have multiple functions, or be recursive, or be iterative.

My Solution

As as sanity check to make sure my assumptions were valid, I did this myself, live:

I wrote this in about 20 minutes and then debugged it for another 10-20 minutes:
(and then I went back for another 2 minutes to fix the leading newline)

"use strict";

var data = {
  foo: [
    {
      bar: [
        {
          baz: ["apples", "bananas"],
        },
      ],
      quux: [
        {
          do: ["red thing", "blue thing"],
        },
      ],
    },
  ],
  grault: {
    name: "Bob",
    age: 37,
    grumpy: false,
    nullish: null,
  },
  answer: 42,
};
/*
 foo:
   - bar:
     - baz:
       - apples
       - bananas
     quux:
       - do:
         - "red thing"
         - "blue thing"
 */

function toYaml(data, prefix = "", skipFirstPrefix = true) {
  // string
  // boolean
  // number
  // array
  // object
  // null
  
  if (["string", "number", "boolean"].includes(typeof data) || null === data) {
    return JSON.stringify(data);
  }
  
  if (Array.isArray(data)) {
    if (!data.length) {
      return "[]";
    }
    return data
      .map(function (val, i) {
        let myPrefix = `\n${prefix}`;
        if (0 === i && skipFirstPrefix) {
          myPrefix = "";
        }
        return `${myPrefix}- ` + toYaml(val, prefix + "  ", true);
      })
      .join("");
  }
  
  // must be an object (or not a valid JSON-able object in the first place)
  let keys = Object.keys(data);
  if (!keys.length) {
    return "{}";
  }
  
  return keys
    .map(function (k, i) {
      let myPrefix = `\n${prefix}`;
      if (0 === i && skipFirstPrefix) {
        myPrefix = "";
      }
      return `${myPrefix}${k}: ` + toYaml(data[k], prefix + "  ", false);
    })
    .join("");
}
@coolaj86
Copy link
Author

Edit: Updated to handle empty arrays and empty objects.

@coolaj86
Copy link
Author

coolaj86 commented Jan 24, 2022

Edit: Accept the way that prettier formats YAML as the preferred way (add back extra leading spaces for arrays under arrays or objects).

Note: this is how I had it originally, but I often see generated YAML that omits the "extra" leading spaces, but trying to do so introduced extra complexity (and a bug) so I checked the output of prettier, found that it matched my original working output, and called it good.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment