A straightforward method to flatten and unflatten JSON files

I've managed to flatten JSON files effortlessly by executing this command in a combination of Node.js and Bash:

npx flat foo.json > bar-flat-output.json
.

But now, I'm searching for another foolproof command that can easily undo the flattening process and restore my JSON files to their original structure.

Answer β„–1

If you're searching for a command to flatten and unflatten JSON in bash, you don't have to limit yourself to just npx flat. There are alternative solutions available, such as using jq.

Let me explain the differences between two versions:

  • Version 1: This code is shorter in length.
  • Version 2: The resulting format of the flattened JSON is more common.

Input JSON

{
   "key1": { "keyA": "valueI" },
   "key2": { "keyB": 2 },
   "key3": { "a": { "b": { "c": 2 } } },
   "key4": [1,[2,[3,4],5],6],
   "key5": true
}

Flatten JSON - Version 1

FLATTENED=$(jq '[ . as $json | paths(scalars) | . as $path | [., ($json | getpath($path))] ]' <<< "$INPUT")
[
  [["key1","keyA"],"valueI"],
  [["key2","keyB"],2],
  [["key3","a","b","c"],2],
  [["key4",0],1],
  [["key4",1,0],2],
  [["key4",1,1,0],3],
  [["key4",1,1,1],4],
  [["key4",1,2],5],
  [["key4",2],6],
  [["key5"],true]
]

Unflatten JSON - Version 1

jq 'reduce .[] as $x (null; setpath($x[0]; $x[1]))' <<< "$FLATTENED"
{
   "key1": { "keyA": "valueI" },
   "key2": { "keyB": 2 },
   "key3": { "a": { "b": { "c": 2 } } },
   "key4": [1,[2,[3,4],5],6],
   "key5": true
}

Flatten JSON - Version 2

FLATTENED=$(jq '
  def key: map(if type == "number" then "[\(tostring)]" else . end) | join(".");
  [ . as $json | paths(scalars) | . as $path | [key, ($json | getpath($path))] ]
  | reduce .[] as $x ({}; .[$x[0]] = $x[1])
' <<< "$INPUT")
{
  "key1.keyA": "valueI",
  "key2.keyB": 2,
  "key3.a.b.c": 2,
  "key4.[0]": 1,
  "key4.[1].[0]": 2,
  "key4.[1].[1].[0]": 3,
  "key4.[1].[1].[1]": 4,
  "key4.[1].[2]": 5,
  "key4.[2]": 6,
  "key5": true
}

Unflatten JSON - Version 2

jq '
  to_entries
  | map(.key |= (split(".") | map(if test("^\\[[0-9]+\\]$"; "") then .[1:-1] | tonumber else . end)))
  | reduce .[] as $x (null; setpath($x.key; $x.value))
' <<< "$FLATTENED"
{
   "key1": { "keyA": "valueI" },
   "key2": { "keyB": 2 },
   "key3": { "a": { "b": { "c": 2 } } },
   "key4": [1,[2,[3,4],5],6],
   "key5": true
}

Answer β„–2

jqg is a Bash script called jqg that can flatten and unflatten JSON data using the tool jq.

Here's an example of how it works with randomly generated JSON:

{
  "dicit": [
    "periculis commune temporibus eripuit",
    "potenti timeam venenatis an",
    292,
    "dissentias class nostrud duis",
    906.641
  ],
  "vestibulum": true,
  "veritus": [
    "consequat rationibus assueverit tota mnesarchum",
    "eligendi lobortis",
    false,
    "prodesset mauris accusam vivendum vel",
    "vero lacinia"
  ],
  "purus": {
    "ubique": "inciderint",
    "errem": "malesuada solet suspendisse dissentiet",
    "ridens": "regione",
    "omnes": {
      "dolorem": true,
      "repudiare": -118,
      "errem": [
        false,
        891.375,
        "dicta feugiat pede accusamus odio",
        "nobis",
        "vehicula option aperiam",
        "massa"
      ]
    }
  },
  "facilisi": 565
}

After using jqg with the command $ jqg . /tmp/rnd.json, the JSON is flattened to:

{
  "dicit.0": "periculis commune temporibus eripuit",
  "dicit.1": "potenti timeam venenatis an",
  "dicit.2": 292,
  "dicit.3": "dissentias class nostrud duis",
  "dicit.4": 906.641,
  "vestibulum": true,
  "veritus.0": "consequat rationibus assueverit tota mnesarchum",
  "veritus.1": "eligendi lobortis",
  "veritus.2": false,
  "veritus.3": "prodesset mauris accusam vivendum vel",
  "veritus.4": "vero lacinia",
  "purus.ubique": "inciderint",
  "purus.errem": "malesuada solet suspendisse dissentiet",
  "purus.ridens": "regione",
  "purus.omnes.dolorem": true,
  "purus.omnes.repudiare": -118,
  "purus.omnes.errem.0": false,
  "purus.omnes.errem.1": 891.375,
  "purus.omnes.errem.2": "dicta feugiat pede accusamus odio",
  "purus.omnes.errem.3": "nobis",
  "purus.omnes.errem.4": "vehicula option aperiam",
  "purus.omnes.errem.5": "massa",
  "facilisi": 565
}

Additionally, jqg can filter the flattened JSON by using the command $ jqg errem /tmp/rnd.json:

{
  "purus.errem": "malesuada solet suspendisse dissentiet",
  "purus.omnes.errem.0": false,
  "purus.omnes.errem.1": 891.375,
  "purus.omnes.errem.2": "dicta feugiat pede accusamus odio",
  "purus.omnes.errem.3": "nobis",
  "purus.omnes.errem.4": "vehicula option aperiam",
  "purus.omnes.errem.5": "massa"
}

If you want to unflatten the filtered JSON, simply use

$ jqg errem /tmp/rnd.json | jqg -u
:

{
  "purus": {
    "errem": "malesuada solet suspendisse dissentiet",
    "omnes": {
      "errem": [
        false,
        891.375,
        "dicta feugiat pede accusamus odio",
        "nobis",
        "vehicula option aperiam",
        "massa"
      ]
    }
  }
}

Please note that I am the creator of this useful tool called jqg.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Converting child dictionaries with identical key names to CSV format using Python's DictWriter

Looking for a solution to format JSON files into CSV files? I have a specific structure in my json file, as shown below: [ {"A":{"value":1}, "B":{"value":2}}, {"A":{"value":9}, "B":{&quo ...

Maintaining personalized variable values for individual connected clients in Node.js: What's the best approach?

I have recently started working with Node.js and I am using Visual Studio 2015 with the Basic Node.js Express 4 app template. After setting some values through a post request from the client, I noticed that when I open another tab and send another post re ...

Can a package-lock.json file be created without running an npm install command?

Is there a way to create only a package-lock.json file without having to redo the npm install process? I'm looking to generate the lock file without reinstalling any of the package files. Is this achievable? ...

What is the most effective way to extract the output from a JSONP request and utilize it beyond the

I have a function that is working well. I had to use JSONP to handle cross-domain issues, and I also wrote an HTTP module to change the content-type. However, I did not include a callback name in the URL. function AddSecurityCode(securityCode, token) { va ...

Merging a Variable with JSON in JSX / React Native

I'm currently working on a weather app that displays custom quotes based on the weather conditions. The code below is functional, but I have multiple quotes for each weather condition. I've managed to generate a random number variable successfull ...

Mocha: Dealing with promises that always time out regardless of the specified time limit

Currently, I am tackling a project for an interview where I need to implement an endpoint that allows me to POST an array of products (listings) and have them created or updated accordingly using MongoDB and Mongoose. The issue I am facing revolves around ...

What is the best way to record data while initiating a process in node.js?

In my latest project, I have implemented a function that spawns a process and requires logging specific information to the console. Here is an example of how this function is structured: function processData(number) { var fileName = settings.file || "de ...

Connecting JSON objects based on unique GUID values generated

I am in search of a method to automate the laborious task of linking multiple JSON objects with random GUIDs. The JSON files are all interconnected: { "name": "some.interesting.name", "description": "helpful desc ...

Which is better: specifying Node.js version with nvmrc or in package.json engines

Ensuring that other developers working on my JavaScript project use specific versions of node and npm is important to me. I recently added the following code snippet to my package.json file: "engineStrict" : true, "engines": { "node" : "10.10.0", ...

populate a MongoDB collection using Node.js

Recently, I have been working on a project where I needed to add values ​​to a table in MongoDB using Node.js. This is the code snippet that I came up with: const mongoose = require('mongoose'); mongoose.connect('mongodb://localhost:2701 ...

Utilizing Business Logic in a MEAN Stack Environment

When developing an Angular application, where should the calculations take place - on the front end or back end? Considering that the outputs need to update with each input change, is it practical to send a request to the back end every time there is an ...

What is the process for integrating CSS and JS into my Express Node localhost server?

I've been struggling to load a basic webpage, only seeing the HTML structure with CSS and JS errors popping up in the console. Here's my index.js code snippet. I attempted using Express static middleware and even tried fetching CSS and JS files s ...

Using Cookies with Next.js and Vercel

I am facing an issue with my NextJs app deployed on Vercel where the cookie is not being set. Upon checking the console in Network, I can see that the request returns a 200 status and the set-cookie value is present without any warning. However, when I loo ...

Link scripts can sometimes cause issues with node.js

Greetings! I have successfully created a client-side SPA using vanilla-router. However, my Node.js server sometimes encounters an error when attempting to load a linked script. Uncaught SyntaxError: Unexpected token '<' This error only oc ...

What is the best way to send a data object to my view using express-handlbars?

Currently, I am utilizing the template engine express-handlbars for my project. Effectively, I can easily insert text into my script using the following code snippet: res.render('index', {foo: "something"}); Subsequently, within my template fil ...

What could be causing the Type Error in jsdom?

When attempting to parse a remote site using jsdom, I encountered an error when trying to use it with node-webkit.js: I received the following error: "Uncaught TypeError: A 'super' constructor call may only appear as the first statement of a f ...

Unable to copy and paste text in a TFX-CLI console using NPM

I'm having trouble pasting text into CLI prompts when using tfx-cli. After installing Node v8.9.1 LTS, the initial installation of tfx-cli hung and I had to cancel it with Ctrl+C. The second attempt was successful, but I noticed a message about &apos ...

Warning: The usage of `--global` and `--local` in the global configuration is no longer supported. Please utilize `--location=global` instead. Additionally, an error has occurred due to an

npm WARN config global `--global`, `--local` are deprecated. Use `--location=global` instead. npm ERR! Unexpected token '.' Everything was working fine on my computer until npm/npx suddenly started throwing this error. The same error pops up ev ...

Encountering an Issue with Installing KeyStone.Js on Windows 7 64-bit Environment

I'm having issues installing keystone.js via Windows command prompt. The installation process throws errors like the following: npm ERR! [email protected] postinstall: `yodoctor` npm ERR! spawn ENOENT npm ERR! npm ERR! Failed at the [email  ...

Getting the name of parameters from Vue 3/Express

Greetings, I want to start by apologizing if the title of my question caused any confusion for those reading it. I struggled to find the right wording. The issue at hand involves a problem with sending a get request from my axios instance to my express ins ...