Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Split payload from JSON String

I receive these huge Strings via WebSocket:

[
  "BTC-31DEC21-100000-P",
  "{\"data\":{\"bids\":{\"0.01\":{\"price\":0.01,\"volume\":66.2,\"exchange\":\"DER\"},\"5.0E-4\":{\"price\":5.0E-4,\"volume\":1.1,\"exchange\":\"DER\"},\"0.637\":{\"price\":0.637,\"volume\":8.4,\"exchange\":\"DER\"}},\"asks\":{\"0.664\":{\"price\":0.664,\"volume\":8.4,\"exchange\":\"DER\"}}},\"isMasterFrame\":true}"
]

or

[
  "BTC-31DEC21-36000-C",
  "{\"data\":[{\"price\":0.422,\"volume\":8.4,\"exchange\":\"DER\",\"side\":\"ASKS\"},{\"price\":0.423,\"volume\":0.0,\"exchange\":\"DER\",\"side\":\"ASKS\"}],\"isMasterFrame\":false}"
]

or

[
  "BTC-31DEC21-60000-P",
  "{\"data\":[{\"price\":0.105,\"volume\":0.0,\"exchange\":\"DER\",\"side\":\"ASKS\"},{\"price\":0.1055,\"volume\":28.7,\"exchange\":\"DER\",\"side\":\"ASKS\"},{\"price\":0.106,\"volume\":7.6,\"exchange\":\"DER\",\"side\":\"ASKS\"},{\"price\":0.1065,\"volume\":43.0,\"exchange\":\"DER\",\"side\":\"ASKS\"}],\"isMasterFrame\":false}"
]

I want to check for isMasterFrame

let payload = JSON.parse(messageString[1]);

if (payload.hasOwnProperty("isMasterFrame")) {
 for (let i = 0; i < payload.pairs.length; i++) {
   let currentPair = payload.data[i]
      currentPair = currentPair.replace(/\0/g, ''); //Remove null chars
       if (currentPair.toUpperCase() != 'KILL') {
           props.onAddAvailablePair(currentPair);
        }
       }
      } else {
             // print some output with payload which holds "isMasterFrame":false
     }

When I run the code I get error:

TypeError: Cannot read properties of undefined (reading 'length')

Data from one inner pair: {\"price\":0.423,\"volume\":0.0,\"exchange\":\"DER\",\"side\":\"ASKS\"} should be split and inserted into the loop one by one

Do you know how I can fix this issue?

like image 258
user1285928 Avatar asked Nov 17 '21 17:11

user1285928


People also ask

How to split first and last name in a JSON string?

You could use the for each loop using Parse JSON and check the attribute and value. Then split first and last name if required by checking the right attribute which in your case "Name and Surname". Hope it make sense. Did I answer your question? Mark my post as a solution! Proud to be a Flownaut! 02-12-2020 09:04 AM

How to convert a JSON column to a table?

An easier method is to go in the query editor and right-click the column and on transform choose JSON, then you expand the JSON you want as columns. 08-09-2017 11:56 PM I try to reproduce your scenario, type the long text in a table. 1. Go to the Query Edit, click split column by comma, you will get the following table.

How to expand a Power Query column to a JSON file?

Please see my Power Query statement as follows. 08-11-2020 01:31 AM An easier method is to go in the query editor and right-click the column and on transform choose JSON, then you expand the JSON you want as columns. 08-09-2017 11:56 PM

How to add attributes to a JSON file?

What you need to do is loop (apply to each) for each element in JSON and based on attribute value add conditions based on the 'attribute' . If your JSON data is always going to be in same format it will be easy. If I have answered your question, please mark your post as Solved. If you like my response, please give it a Thumbs Up.


Video Answer


4 Answers

Your data has different structure when isMasterFrame is different. You have Object of bids and asks in data when isMasterFrame is true while it is an array when isMasterFrame is false.

const data1 = [
    "BTC-31DEC21-100000-P",
    "{\"data\":{\"bids\":{\"0.01\":{\"price\":0.01,\"volume\":66.2,\"exchange\":\"DER\"},\"5.0E-4\":{\"price\":5.0E-4,\"volume\":1.1,\"exchange\":\"DER\"},\"0.637\":{\"price\":0.637,\"volume\":8.4,\"exchange\":\"DER\"}},\"asks\":{\"0.664\":{\"price\":0.664,\"volume\":8.4,\"exchange\":\"DER\"}}},\"isMasterFrame\":true}"
  ],
  data2 = [
    "BTC-31DEC21-36000-C",
    "{\"data\":[{\"price\":0.422,\"volume\":8.4,\"exchange\":\"DER\",\"side\":\"ASKS\"},{\"price\":0.423,\"volume\":0.0,\"exchange\":\"DER\",\"side\":\"ASKS\"}],\"isMasterFrame\":false}"
  ]
data3 = [
  "BTC-31DEC21-60000-P",
  "{\"data\":[{\"price\":0.105,\"volume\":0.0,\"exchange\":\"DER\",\"side\":\"ASKS\"},{\"price\":0.1055,\"volume\":28.7,\"exchange\":\"DER\",\"side\":\"ASKS\"},{\"price\":0.106,\"volume\":7.6,\"exchange\":\"DER\",\"side\":\"ASKS\"},{\"price\":0.1065,\"volume\":43.0,\"exchange\":\"DER\",\"side\":\"ASKS\"}],\"isMasterFrame\":false}"
];

const formatData = (data) => {
  return data.reduce((r, o) => {
      Object.entries(o).forEach(([k,v]) => {
        r[k] ??= [];
        r[k].push(v);
      });
      return r;
    }, {})
}

[data1, data2, data3].forEach(data => {
  const o = JSON.parse(data[1]);
  if(o.isMasterFrame) {
    const result = formatData(Object.values(o.data.bids));
    console.log(result);
  } else {
    const result = formatData(o.data);
    console.log(result);
  }
});
like image 76
Hassan Imam Avatar answered Oct 23 '22 14:10

Hassan Imam


Problem

You don't have property pairs inside payload object, so you can not access its length.

Solution

You should iterate over data property. Since data property is also object, you can use Object.keys() function and iterate over its sub-properties.

let payload = JSON.parse(messageString[1]);

if (payload.hasOwnProperty("isMasterFrame")) {
  for (let i = 0; i < Object.keys(payload.data).length; i++) {
    let current_property= payload.data[Object.keys(payload.data)[i]];
    console.log(current_property);
    ...
like image 43
NeNaD Avatar answered Oct 23 '22 13:10

NeNaD


  1. pairs property is not found inside object.
  2. String replace() method to replace a substring in a string with a new one. Here currentPair is a Object.If you try to replace any value of object just put if after currentPair ex: currentPair.exchange.replace(/\0/g, '');
  3. if (currentPair.toUpperCase() != 'KILL') this condition is not clear to me, you may try to match kill with any object value. you may use like this (currentPair.side.toUpperCase() != 'KILL')

     var messageString = [
             "BTC-31DEC21-60000-P",
             "{\"data\":[{\"price\":0.105,\"volume\":0.0,\"exchange\":\"DER\",\"side\":\"ASKS\"},{\"price\":0.1055,\"volume\":28.7,\"exchange\":\"DER\",\"side\":\"ASKS\"},{\"price\":0.106,\"volume\":7.6,\"exchange\":\"DER\",\"side\":\"ASKS\"},{\"price\":0.1065,\"volume\":43.0,\"exchange\":\"DER\",\"side\":\"ASKS\"}],\"isMasterFrame\":false}"
         ]
    let payload = JSON.parse(messageString[1]);

    if (payload.hasOwnProperty("isMasterFrame")) {

        for (let i = 0; i < payload.data.length; i++) { //change here[1]
            let currentPair = payload.data[i]
            console.log(`current ${i} pair is- `,currentPair);
            // currentPair = currentPair.replace(/\0/g, ''); //change here[2]
            //  if (currentPair.toUpperCase() != 'KILL') { //change here[3] 
            //    props.onAddAvailablePair(currentPair);
            // }
        }
    } else {
        //print some output with payload which holds "isMasterFrame":false
    }

Output:
current 0 pair is-  {price: 0.105, volume: 0, exchange: 'DER', side: 'ASKS'}
current 1 pair is-  {price: 0.1055, volume: 28.7, exchange: 'DER', side: 'ASKS'}
current 2 pair is-  {price: 0.106, volume: 7.6, exchange: 'DER', side: 'ASKS'}
current 3 pair is-  {price: 0.1065, volume: 43, exchange: 'DER', side: 'ASKS'}
like image 2
MD. RAKIB HASAN Avatar answered Oct 23 '22 13:10

MD. RAKIB HASAN


I kinda cannot make heads and tails of what you are trying to achieve but here you have it.
your payload.data (and mine decodedPayloadData.data) is and object and not an array so lenght will throw error. That is why you can use Object.entries to get array of elements from this object and then iterate it.

I have added iterateObject() function just to be fancy with displaying data.

const data = [
    [
        "BTC-31DEC21-100000-P",
        "{\"data\":{\"bids\":{\"0.01\":{\"price\":0.01,\"volume\":66.2,\"exchange\":\"DER\"},\"5.0E-4\":{\"price\":5.0E-4,\"volume\":1.1,\"exchange\":\"DER\"},\"0.637\":{\"price\":0.637,\"volume\":8.4,\"exchange\":\"DER\"}},\"asks\":{\"0.664\":{\"price\":0.664,\"volume\":8.4,\"exchange\":\"DER\"}}},\"isMasterFrame\":true}"
    ],
    [
        "BTC-31DEC21-36000-C",
        "{\"data\":[{\"price\":0.422,\"volume\":8.4,\"exchange\":\"DER\",\"side\":\"ASKS\"},{\"price\":0.423,\"volume\":0.0,\"exchange\":\"DER\",\"side\":\"ASKS\"}]}"
    ],
    [
        "BTC-31DEC21-60000-P",
        "{\"data\":[{\"price\":0.105,\"volume\":0.0,\"exchange\":\"DER\",\"side\":\"ASKS\"},{\"price\":0.1055,\"volume\":28.7,\"exchange\":\"DER\",\"side\":\"ASKS\"},{\"price\":0.106,\"volume\":7.6,\"exchange\":\"DER\",\"side\":\"ASKS\"},{\"price\":0.1065,\"volume\":43.0,\"exchange\":\"DER\",\"side\":\"ASKS\"}],\"isMasterFrame\":false}"
    ]
];

const iterateObject = (params) => {
    Object.entries(params).map(([name, value]) => {
        if (typeof value === 'object') {
            console.log('name:', name, '{');
            iterateObject(value);
            console.log('}');
        } else {
            console.log('name:', name, '; value:', value);
        }
    });
};

data.map(payload => {
    const decodedPayloadData = JSON.parse(payload[1]);

    if (decodedPayloadData.hasOwnProperty('isMasterFrame') && decodedPayloadData.isMasterFrame === true) {
        Object.entries(decodedPayloadData?.data ?? {}).map(([_, params]) => {
            if (typeof params === 'object') {
                iterateObject(params);
            } else {
                console.log('name:', name, '; value:', value);
            }
        });
    } else {
        console.log('isMasterFrame is not defined or is not `true`');
    }
    console.log('----------------');
});
.as-console-wrapper {
  max-height: unset !important;
  top: 0;
}
like image 2
ciekals11 Avatar answered Oct 23 '22 13:10

ciekals11