Brygom
Brygom

Reputation: 848

Typescript create JSON Object Using Interface

I need to build a custom JSON object for store in PostgreSQL in json field and i use typescript for do this.

In my testing case i have this code:

interface Product {
  id: number,
  quantity: number,
}

let prod: Product = {} as any;
interface Products extends Array<Product>{}
let productItems : Products = [];
let productItems2 : Products = [];


let obj = {};
let container = [];

prod.id = 1;
prod.quantity = 10;
console.log("prod1: ", prod);
productItems.push(prod);

prod.id = 2;
prod.quantity = 100;
console.log("prod2: ", prod);
productItems.push(prod);

prod.id =3;
prod.quantity = 34;
console.log("prod3: ", prod);
productItems.push(prod);

obj = { "products1" : productItems}
container.push(obj);

prod.id = 10;
prod.quantity = 10;
console.log("prod2.1: ", prod);
productItems2.push(prod);

prod.id = 20;
prod.quantity = 100;
productItems2.push(prod);
console.log("prod2.2: ", prod);

prod.id =30;
prod.quantity = 34;
console.log("prod2.3: ", prod);
productItems2.push(prod);

obj = { "products2" : productItems2}
container.push(obj);

obj = { "products1" : productItems, "products2": productItems2}

console.log(JSON.stringify(obj));

For some reason when show in console the content for var productItems, always display the last item prod.id = 30 and prod.quantity = 34.

The array not stored the data for every new product but in console i can see the correct values for every new item.

My required is get an object equal to obj with correct values as follow:

{
    "products1": [{
        "id": 1,
        "quantity": 10
    }, {
        "id": 2,
        "quantity": 100
    }, {
        "id": 3,
        "quantity": 34
    }],
    "products2": [{
        "id": 10,
        "quantity": 10
    }, {
        "id": 20,
        "quantity": 100
    }, {
        "id": 30,
        "quantity": 34
    }]
}

If i print the var container display a JSON object into [] like array.

What i do wrong?

Here i have my code play https://stackblitz.com/edit/typescript-3nfapq?file=index.ts

Upvotes: 1

Views: 4981

Answers (1)

jacobm
jacobm

Reputation: 14025

The issue is that you're repeatedly mutating the same object rather than making a new object for every item you want to add to the array.

The issue centers on the difference between variables and values. To see what I mean, let's walk through a part of your code. We start with

let prod = {};

which declares the variable prod and assigns it the value of an initially-empty object in some memory location -- let's say location 1.

Then we hit:

prod.id = 1;
prod.quantity = 10;

This modifies the object prod refers to -- the object at location 1 -- so that it now has id 1 and quantity 10. The next line,

productItems.push(prod);

pushes the object at location 1 onto productItems. So far so god. But next, we have:

prod.id = 2;
prod.quantity = 100;
productItems.push(prod);

This again changes the object at location 1 to have id 2 and quantity 100, and then again pushes that object onto productItems. So at this point, the object at location 1 is {id: 2, quantity: 100} and productItems contains two references to it.

To fix this, you need to avoid reusing the same object. You can still use the same variable prod if you want, but you need it to refer to a different object every time you make a new one to put in the array. So for instance, if you wrote:

let prod = {} as any;
prod.id = 1;
prod.quantity = 10;
console.log("prod1: ", prod);
productItems.push(prod);

prod = {} as any;
prod.id = 2;
prod.quantity = 100;
console.log("prod2: ", prod);
productItems.push(prod);

prod = {} as any;
prod.id =3;
prod.quantity = 34;
console.log("prod3: ", prod);
productItems.push(prod);

then things work as you'd expect.

Upvotes: 2

Related Questions