Changing the names of properties within a intricate JSON structure

I have a JSON data structure that is quite complex, like the one shown below:

const json = '{"desc":"zzz", "details": { "id": 1, "name": "abc", "categoryDetails": { "cid": 1, "name": "abc" } }}'

The task at hand is to write code that can dynamically rename keys within this JSON structure. Here's what I have attempted so far:

const obj = JSON.parse(json);

var renameKeys = [
    { 
        oldKey: 'desc',
        newKey: 'newdesc'
    },
    { 
        oldKey: 'details.name',
        newKey: 'details.newname'
    },
    { 
        oldKey: 'details.categoryDetails.name',
        newKey: 'details.categoryDetails.newname',
    }
];

for (var i in renameKeys) {
    var item = renameKeys[i];
    if(obj[item.oldKey]) { //this throws error - undefined. It is possible that this key does not exist in some objects
        obj[item.newKey] = obj[item.oldKey];
        delete obj[item.oldKey];
    }
}

Unfortunately, running this code snippet results in undefined errors (TypeError: Cannot read properties of undefined) with the for loop.

Despite the complexity of the JSON paths, we need to persist with this approach of defining old and new keys in order to correct hundreds of JSON documents.

How can we modify the renameKeys array and the for loop to ensure that this logic works correctly?

Answer №1

When it comes to accessing or assigning deeply nested keys using dot notation (e.g. 'details.name'), it's important to note that in plain JavaScript / TypeScript, the behavior may not be what you expect. Instead of diving into nested objects, it simply treats the key as a string with the actual dot included:

{
  'details.name': "some value",
}

What you might have intended was something like this:

{
  details: {
    name: "some value",
  },
}

To properly handle translating strings with dot notation into paths for potentially deep nesting, you can leverage Lodash's utility functions such as get, set, and unset:

Retrieve the value at specified path within an object.

Assign a value to the specified path within an object, creating intermediate properties if necessary.

Delete a property found at the specified path within an object.

if (_.get(obj, item.oldKey)) {
  _.set(obj, item.newKey, _.get(obj, item.oldKey));
  _.unset(obj, item.oldKey);
}

Check out the live demonstration here: https://jsbin.com/tenapul/edit?js

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

Speedy Typescript inquiry query

I'm currently in the process of creating a basic endpoint by following the Fastify with Typescript documentation linked below: https://www.fastify.io/docs/v3.1.x/TypeScript/ export default async function customEndpoint(fastify: any) { const My ...

In Typescript, is it possible to utilize the value from a particular key in a type declaration as the type for another key within the same declaration?

Consider a scenario where I am designing a Variable type that includes a key named type with a value of type string. Is there a method to extract the value from the type key and utilize it as the type for another key within the declaration, without resorti ...

Developing a dynamic modal using Angular and embedding Google Maps within an iframe

I'm currently working on implementing a modal in my Angular application that, when opened, displays Google Maps within an iframe. The problem I'm facing is that the iframe isn't loading and I'm receiving this error in the browser conso ...

Creating custom typings in a typings.d.ts file does not address the issue of importing a JavaScript library

I'm attempting to integrate the Parse-server JS sdk into an angular 8 application, but no matter what approach I take, I encounter errors. Here is what I have tried: Creating custom typings.d.ts files with declare var parse: any; Installing the @ty ...

Enforcement of static methods in Typescript abstract classes is not mandatory

In my TypeScript code, I have a simple structure defined: abstract class Config { readonly NAME: string; readonly TITLE: string; static CoreInterface: () => any } class Test implements Config { readonly NAME: string; readonly TITL ...

Challenges accessing all columns of a single model in Rails and AngularJS view

While working on my Rails application, I encountered an issue when trying to retrieve details of the logged-in user using an AngularJS service. The JSON data fetched from the server only displays a few columns instead of all the columns present in the mode ...

Custom properties of an object are being erased when converting to JSON format within the canvas

I am working on a canvas project that involves multiple image objects, each with custom attributes. My goal is to save this canvas as a json object in a database, but the conversion process seems to strip away the custom attributes. Currently, I am using t ...

Discovering the presence of a NAN value within a JSON string

Consider the following scenario: I have a function that receives jsonData in JSON format, and I want to validate the variable jsonData to check for NaN. How can I achieve this? function save() { var jsonData = getEnteredValue(); $.ajax({ ...

Implementing React custom component with conditional typing

My goal is to enable other developers to set a click handler for a button only if the button's type is set to button. Users can only set the type to either button or submit. I want to restrict developers from setting the onClick property on the comp ...

JSON is not validated

I have been attempting to validate the following code on json, but I continuously encounter an "expected string" error. Can someone please assist me with this? { 'auth.login': { 'url': 'https: //api.optionshouse.com/m', ...

The Ghostly Glare of Doom: Ionic 2 Strikes on Android

While my application runs smoothly in the browser, I encounter an error when trying to run it on my device. The issue is as follows: 0 758771 log deviceready has not fired after 5 seconds. 1 758797 log Channel not fired: onDOMConte ...

Retrieving precise information from a Json file with PHP

Hey there, I have a JSON file and I'm looking to extract certain data from it. Here's how the file appears: { "took" : 1, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, ...

How to display JSON data in a custom format using PHP's json_encode with the JSON_PRETTY_PRINT option?

As we know, PHP has the JSON_PRETTY_PRINT option to format JSON data. But what if a different format is desired? $message = array( "Open all day" => "Sundays,Saturdays,12-12-2013, 14-10-2013", "Availabilty" => array( "12/12/2013" =& ...

Traversing through JSON data in Flutter using iterable

Hey everyone, I'm facing an issue that I need help with. I recently made a successful get request through an API using Flutter. The problem I have is related to a 'mentee id' list that I received from the previous screen. Here is what it loo ...

Opera's compatibility with jQuery's Append method allows developers to

I recently wrote a jQuery script that interacts with a JSON feed and dynamically creates HTML code which is then added to a designated div on my WordPress site. Surprisingly, the functionality works flawlessly in all browsers except for Opera - where not ...

Having trouble declaring a module in an npm package with Typescript?

I'm currently working on a project using Vue.js and TypeScript. Within project "A," I am utilizing a private npm package called "B," which serves as a component library. This package "B" also incorporates another library, 'tiptap,' which unf ...

Best practices for implementing the map function with TypeScript

I'm currently working on mapping types in a DB using the Map function in JavaScript. This is my first time trying to do this, and I'm eager to learn but I've hit a roadblock. Here is the structure of the DB: const db = { data: [ { ...

"The debate over using 'stringly typed' functions, having numerous redundant functions, or utilizing TypeScript's string enums continues to divide the programming

I have a specific object structure that contains information about countries and their respective cities: const geo = { europe: { germany: ['berlin', 'hamburg', 'cologne'], france: ['toulouse', ' ...

Support for ViewEncapsulation.ShadowDom now available in Edge, Internet Explorer, and legacy browsers

I am working with Angular 7 and material design. Some of my components utilize ShadowDOM ViewEncapsulation, leading to errors in older versions of IE, Edge, Chrome, and Firefox. Below is the error message I am encountering: Object doesn't support pr ...

Experiencing constant errors with axios requests in my MERN Stack project using a Typescript Webpack setup

Hey there, I'm in need of some help! I've been working on a MERN Stack project and have set up Webpack and Babel from scratch on the frontend. However, every time I send a request to my Node Server, I keep getting an error message back. Can anyon ...