Javascript JSON update

Hi folks, am learning about javascript and need assistance and best practise in regards performance.

I have an JSON object that need to be updated before being parsed into a JSX component.

Source JSON obj:

var Obj = { "data": [
  {"id":1, "text":"Task #1", "project":"10", "sub_project":"10-1" },
  {"id":2, "text":"Task #2", "project":"10", "sub_project":"10-1" },
  {"id":3, "text":"Task #3", "project":"11", "sub_project":"11-1" }
]};

Required JSON obj result:

var Obj = { "data": [
  {"id":10, "text":"Project 10" },
  {"id":11, "text":"Project 11" },
  {"id":10-1, "text":"Sub Project 10-1", "project":"10" },
  {"id":11-1, "text":"Sub Project 11-1", "project":"11" },
  {"id":1, "text":"Task #1", "project":"10", "sub_project":"10-1" },
  {"id":2, "text":"Task #2", "project":"10", "sub_project":"10-1" },
  {"id":3, "text":"Task #3", "project":"11", "sub_project":"11-1" }
]};

What’s the best way to update this JSON object “data” to return the required result. The JSON source has only tasks items, but need to extract (unique projects and sub-projects) then include/append these to source JSON obj. Any advice are highly appreciated.

You can’t update JSON, it’s just a blob of text, it’s just the form in which the data gets transported to you. What you mean is that you want to remap the incoming data: you don’t need to go into the object and update it, what you’re going to want to do is extract that data property, then loop over it and build a new array from the data in it; that array is the thing that will be your React app’s state.

However, the data structure you want to transform to doesn’t really make sense:

  1. Each item has an ID.
  2. Items belong to a project, which has a string ID
  3. Items belong to a subproject, which is indicated with a string ID of {project ID}-{subproject ID}.

So this doesn’t make sense unless there is some context you’ve missed off:

[
  // These are projects
  {"id":10, "text":"Project 10" },
  {"id":11, "text":"Project 11" },
  // These are subprojects
  {"id":10-1, "text":"Sub Project 10-1", "project":"10" },
  {"id":11-1, "text":"Sub Project 11-1", "project":"11" },
  // These are items
  {"id":1, "text":"Task #1", "project":"10", "sub_project":"10-1" },
  {"id":2, "text":"Task #2", "project":"10", "sub_project":"10-1" },
  {"id":3, "text":"Task #3", "project":"11", "sub_project":"11-1" }
]

So there are actually three different sets of interlinked data there, but you are trying to jam them all together, and that’s going to make it nearly impossible to easily render accurate output.

  • There is a set of projects, with IDs
  • Projects can have subprojects, which have IDs, and each belong to a project
  • There is a set of items, which belong to a subproject (and therefore a project)

You can’t put them all together. For one thing, each item has an id key. What happens when you have 10 items? In your data structure, you will have two things with id key of 10 that represent completely different concepts.

Thanks DanCouper,

A small revision of new simplified expected dataset (after extract/append methods):

var Obj = { "data": [
  {"id":10, "text":"Project 10" },
  {"id":11, "text":"Project 11" },
  {"id":10-1, "text":"Sub Project 10-1", "parent":"10" },
  {"id":11-1, "text":"Sub Project 11-1", "parent":"11" },
  {"id":1, "text":"Task #1", "parent":"10-1" },
  {"id":2, "text":"Task #2", "parent":"10-1" },
  {"id":3, "text":"Task #3", "parent":"11-1" }
]};

Any suggestion in regards methods on how to:

  1. extract “project” and “sub_project” prop/values tasks.project[]
  2. create new arrays for project and sub_project
  3. append new arrays to exisiting Obj array or new

This second data structure makes a lot more sense than the first. Your ‘id’ field does need to be a string, since 10-1 isn’t a valid number value (JSON isn’t going to subtract them after all).

I don’t understand the steps 1-3 you posted, and it sounds like your own understanding of them isn’t clear either. Are you trying to transform this object into another form? Can you give an example of what your intended output is?

Edit: Sorry, I’m still half-asleep, and didn’t see that the second data structure is your intended output. Still, neither of them are valid JSON, so I’m wondering where this source data is coming from. Is it an exercise from a book or something?

It’s still not going to work, that isn’t really simplified (though it does make slightly more sense), because these:

  {"id":1, "text":"Task #1", "parent":"10-1" },
  {"id":2, "text":"Task #2", "parent":"10-1" },
  {"id":3, "text":"Task #3", "parent":"11-1" }

Are not the same kind of thing as these:

  {"id":10-1, "text":"Sub Project 10-1", "parent":"10" },
  {"id":11-1, "text":"Sub Project 11-1", "parent":"11" },

Which are not the same kind of thing as these:

  {"id":10, "text":"Project 10" },
  {"id":11, "text":"Project 11" },

By putting them all in one array, and giving them each a sequential ID, you are saying they are the same thing, and they aren’t.

If you have a list of data that you are going to render out, then that data should all be of exactly the same shape. With a list of objects, that means every object in the list should have exactly the same fields, and the value of each of those fields should be exactly the same type (with the caveat that there may be null values if data is missing). The original object you got back is an example of that.

I you don’t do that, it means you need to write logic to change how the rendering works based on both what fields are in each object and what the types of the values are, which makes things both complicated and very fragile


This is an example of a possible data structure that would work, though I’m doing this in a hurry so it’s a bit flawed:

state = {
  projects: {
    "10": {
      subProjects: ["10.1"],
    },
    "11": {
      subProjects: ["11.1"]
    },
  },
  subProjects: {
    "10-1": {
      project: "10",
      items: [1,2],
    },
    "11-1": {
      project: "11",
      items: [3]
    },
  },
  items: {
      1: { id:1, text: "Task #1", project: "10", subProject: "10-1" },
      2: { id:2, text: "Task #2", project: "10", subProject: "10-1" },
      3: { id:3, text: "Task #3", project: "11", subproject: "11-1" }
  }
}

I still don’t really like this, but it’s now extremely easy to render out all the items, or all the projects, or a project and the subbrojects and the items in it and so on. And I can add descriptive text or other metadata to each of the sub/projects individually.