Skip to content

Fill the empty values in my JSON (not null or “”)

I have a raw data that looks like that :

{SKT_CD:01582030,SKT_DATE:2021/04/12,SKT_TIME:21,SO2:0,NO:0,NO2:0.002,NOX:0.003,CO:,OX:,NMHC:,CH4:,THC:,SPM:0.008,PM2_5:,SP:},{SKT_CD:01582030,SKT_DATE:2021/04/12,SKT_TIME:22,SO2:0,NO:0,NO2:0.002,NOX:0.002,CO:,OX:,NMHC:,CH4:,THC:,SPM:0.010,PM2_5:,SP:}, and more

I need to fill those empty values to be able to use it as an object. It’s not me who create it, I got it from an external source. I know how to fill those empty values if they were like “” or null. Sometime there is a coma after the empty value and sometime nothing like for the last key. I’m a beginner and I can’t figure a way of doing that. Is that even possible?

Answer

Updated response

If you data looks like that, you need to change your algorithm for parsing. Just remove the leading opening-brace and ending closing-brace and split by /},s*{/.

const rawData = `{SKT_CD:01582030,SKT_DATE:2021/04/12,SKT_TIME:21,SO2:0,NO:0,NO2:0.002,NOX:0.003,CO:,OX:,NMHC:,CH4:,THC:,SPM:0.008,PM2_5:,SP:},{SKT_CD:01582030,SKT_DATE:2021/04/12,SKT_TIME:22,SO2:0,NO:0,NO2:0.002,NOX:0.002,CO:,OX:,NMHC:,CH4:,THC:,SPM:0.010,PM2_5:,SP:}`;

const obj = rawData
  .substring(rawData.indexOf('{') + 1, rawData.lastIndexOf('}'))
  .split(/},s*{/)
  .map(line => Object.fromEntries(line.split(/,(?=w+:)/g)
    .map(pair => pair.split(/(?<=^w+):/))
    .filter(([key, value]) => value)
    .map(([key, value]) =>
      [key, value ? !isNaN(value) ? Number(value) : value : null])))

console.log(obj);
.as-console-wrapper { top: 0; max-height: 100% !important; }

Original response

If you need to convert this non-JSON compliant data to a JavaScript object, you could split the lines and reduce them with an object.

You can split the key-value pairs after trimming and removing the end commas. I used a positive look-behind to check for an alphanumeric sequence of characters prior to the colon.

const rawData = `{
  SKT_CD:01101010,
  SKT_DATE:2021/04/01,
  SKT_TIME:01,
  SO2:0,
  NO:0,
  NO2:0.006,
  NOX:0.006,
  CO:,
  OX:0.039,
  NMHC:0.07,
  CH4:2.01,
  THC:2.08,
  SPM:0.008,
  PM2_5:0,
  SP:
}`;

const obj = rawData
  .substring(rawData.indexOf('{') + 1, rawData.lastIndexOf('}'))
  .trim()
  .split('n')
  .reduce((acc, line) =>
    (([key, value]) =>
      ({
        ...acc,
        [key]: value ? !isNaN(value) ? Number(value) : value : null
      }))
    (line.trim().replace(/,$/, '').split(/(?<=^w+):/)), {});

console.log(obj);
.as-console-wrapper { top: 0; max-height: 100% !important; }

If you need to filter-out the pairs with an empty value, you can map prior to filtering and converting to to an object (from entries).

const rawData = `{
  SKT_CD:01101010,
  SKT_DATE:2021/04/01,
  SKT_TIME:01,
  SO2:0,
  NO:0,
  NO2:0.006,
  NOX:0.006,
  CO:,
  OX:0.039,
  NMHC:0.07,
  CH4:2.01,
  THC:2.08,
  SPM:0.008,
  PM2_5:0,
  SP:
}`;

const obj = Object.fromEntries(rawData
  .substring(rawData.indexOf('{') + 1, rawData.lastIndexOf('}'))
  .trim()
  .split('n')
  .map((line) =>
    (([key, value]) =>
      [key, value ? !isNaN(value) ? Number(value) : value : null])
    (line.trim().replace(/,$/, '').split(/(?<=^w+):/)))
  .filter(([key, value]) => value != null));

console.log(obj);
.as-console-wrapper { top: 0; max-height: 100% !important; }