Problem to replace a JSON object in Array

Hi , I have a question which might be more related to JS than Node Red.....

I'm trying to replace a JSON object in a Array but can't get it work. Each time the new data replaced in the array is a string, but not an object. I tried different ways, but no luck.

However, when I set the same object to a new object in the same array, then it works perfectly....

Here is a snippest of the code I use to manipulate data before sending it back into the array :

var csv = global.get("csvContent");

// When device name info provided from DB : 
if (msg.topic == "DB_Device_Name" && flow.get("DeviceType") != "Not Set !") {
    for (let i = 0; i < csv.length; i++) {
      
        // Build final end point name :

        var descriptorDesc = csv[i].descriptor.desc;
        var descriptorLabel = csv[i].descriptor.label; //>> {desc:,label:01C01-VGW1_CH07_RxA04}
        node.warn("descriptorLabel " + descriptorLabel)

        descriptorLabel = msg.payload + "_CH0" + csv[i].chNumber + csv[i].rxTx + csv[i].vertexType + csv[i].audCh;

       let newDesc = {"desc" : descriptorDesc}
       let newLabel = {"label" : descriptorLabel}
        csv[i].descriptor = Object.assign({}, newDesc, newLabel )

        csv[i].test = Object.assign({}, newDesc, newLabel )

    }

global.set("csvContent", csv);

When I want to replace descriptor here is the result ( I also put some screenshots, as the code section does not show any difference) :

image

{"desc":"","label":"12345_CH07_RxA04"}

when I set it to csv[i].test :

image

{"desc":"","label":"12345_CH07_RxA04"}

If useful, here is also a copy of one of the objects from csvContent source ( and dest) global variable :

{"#":"device73.484735f6-a1ea-596e-8282-0cd1108e6be2.R01a52f67-554c-5791-8503-fcbee07f93d9","active":"true","bidirPartnerId":"null","codecFormat":"Audio","configPriority":"off","control":"off","custom":"{}","descriptor":"{\"desc\":\"\",\"label\":\"12345_CH07_RxA04\"}","extraAlertFilters":"[]","Factory label":"receiver_s06_a03","isIgmpSource":"false","mainDstIp":"null","mainDstMac":"null","mainDstPort":"null","mainDstVlan":"null","mainSrcGateway":"null","mainSrcIp":"null","mainSrcMac":"null","mainSrcNetmask":"null","public":"false","sdpSupport":"true","sipsMode":"NONE","spareDstIp":"null","spareDstMac":"null","spareDstPort":"null","spareDstVlan":"null","spareSrcGateway":"null","spareSrcIp":"null","spareSrcMac":"null","spareSrcNetmask":"null","tags":"[]","useAsEndpoint":"false","chNumber":7,"vertexType":"A","rxTx":"_Rx","audCh":"04","test":{"desc":"","label":"12345_CH07_RxA04"}}

Thanks to you in advance for your tips !

Not certain why that would be happening without adding some debugging etc. However, I'd likely side step the issue and simply assign a new object explicitly:

        csv[i].descriptor = {
           "desc" : descriptorDesc,
           "label" : descriptorLabel
        }

Note, you may have something affecting the context data by reference in another part of your flow (that's my disclaimer)

In CsvContent the property descriptor is a string, so you can not assign a object property to a string. Unless as in @Steve-Mcl suggestion you assign descriptor as an object.

Mmm sorry I sent a copy of the CSV after it was modified by the non-working script...

I can definitely say it's an object at start, otherwise the script would not even be able to build the csv[i].test object....

I think I checked already the other nodes in the flow, but @Steve-Mcl might be right, there might something which also brings modification to the problematic obj in the array.... I can't see any other reason right now.

Hi, I found where my problem comes from, but still can't explain it.

Downstream in the flow after setting up the descriptor value as an object, I have a node which stringify it, only to be displayed correctly in a table :

image

The code of this second node is :

// Manage datas for proper display in table : 
var csv = global.get("csvContent");

    for (let i = 0; i < csv.length; i++) {

        csv[i].descriptor = JSON.stringify(csv[i].descriptor);
    }

msg.payload = "setdata"

msg.data = csv;

return msg;

As you can see the output of this node right now is not connected anywhere, and I don't make use of global.set() to write back the array..... but the global stored array is being modified.

image

As soon as I remove the link to this node, everything is fine :

image

am I missing something obvious ?

Thanks

Object are stored in one memory slot, and are passed by reference.
So csv = global.get("csvContent") Tell js to reference the same memory. When you change csv the global is changed to as they reference the same memory
try
csv = RED.util.cloneMessage(global.get("csvContent"))

https://nodered.org/docs/api/modules/v/0.20.0/@node-red_util_util.html#.cloneMessage

ok thank you, it works.

I'll need to have a serious look on all this. My (wrong) guess was that a variable stored in any context could not be modified until we use any kind of context.set() to write it back....

For primitive types, that would be correct.

  • strings
  • integers
  • booleans
  • etc etc

But for complex types

  • Arrays
  • Objects
  • classes
  • etc etc

They are pass-by-ref

It's not Node RED behaving this way, more how javascript works

EDIT
Oh - just seen the link provided by @E1cid that explains.

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.