1

I have a JSON object I am loading from an API, I am then formatting the JSON and loading it into an editable DIV.

JSON.stringify(JSON.parse(rawJson.replace(/\s+/g, ' ').trim()), null, 1)

My current issue is that I would like to maintain order when the JSON string loads, right now it loads in random order.

the function that processes the JSON

// process incoming JSON template
  const processJSON = async (json: any, keys?: any[]) => {

    if (json) {
      let _matches = []
      let _unMatch = [];

      // format json for display
      const jsonString = json && JSON.stringify(json, null, 1);
      // update the match keys with default values

      if (!keys) {

        // get all default keys
        const matches = jsonString.match(/{{(([^}][^}]?|[^}]}?)*)}}/gm);

        const defaultMatchClean = matches && matches.map(match => {
          //return match
          return match.replace(/{{|}}/gm, '')
        })


        defaultMatchClean && defaultMatchClean.forEach(match => {
          _matches = [..._matches, { selectedString: match, key: match }]
          _unMatch = [..._unMatch, { key: match, html: match }]
        })

        // // rebuild display  with default values
        if (matches) {
          matchKeys.current = _matches;
          unMatch.current = _unMatch
        }

        selectedRef.current = jsonString;
        setSelectedJSON(jsonString);
        console.log(" ~ file: AlertBody.tsx ~ line 121 ~ processJSON ~ json", JSON.stringify(json), _matches)
        return
      }



      matchKeys.current = keys ? keys : _matches;;
      matchKeys.current.forEach(match => {
        _unMatch = match.key.includes('pw') ? [..._unMatch, { key: match.key, html: match.key }] :
          [..._unMatch, { key: match.selectedString, html: match.key }]
      })

      unMatch.current = _unMatch
      selectedRef.current = jsonString;

      setSelectedJSON(jsonString);
      console.log(" ~ file: AlertBody.tsx ~ line 121 ~ processJSON ~ json", jsonString)
    }
  }

sample JSON

{ "blocks": [{"text": {"type": "plain_text","text": "{{pw.alert.severity}} - {{pw.alert.title}}"},"type": "header"} ], "attachments": [{"color": "{{pw.state.severityColor}} - {{pw.alert.title}}","blocks": [{"type": "section","text": {"type": "plain_text","text": "Triggered: {{pw.alert.timestamp.iso}}"}},{"type": "section","text": {"text": "{{pw.alert.description}}","type": "mrkdwn"}},{"type": "actions","elements": [{"type": "button","value": "View Alert","action_id": "button-action-1","text": {"text": "View Alert","type": "plain_text","emoji": true},"url": "{{pw.alert.alertUrl}}"}]},{"type": "header","text": {"type": "plain_text","text": "CORRELATIONS"}},{"type": "section","text": {"type": "mrkdwn","text": "<{{pw.link.openall}} | *Open All*> | <{{pw.link.downloadall}} | *Download All*>"}},{"text": {"type": "plain_text","emoji": true,"text": "{{pw.workflow.destinationGroup.1.name}}"},"type": "header"},{"type": "divider"},{"type": "section","text": {"type": "mrkdwn","text": "<{{pw.workflow.destinationGroup.1.destination.0.url}} | * {{pw.workflow.destinationGroup.1.destination.0.name}}*>"}},{"text": {"text": "<{{pw.workflow.destinationGroup.1.destination.1.url}} | * {{pw.workflow.destinationGroup.1.destination.1.name}}*>","type": "mrkdwn"},"type": "section"},{"type": "section","text": {"text": "<{{pw.workflow.destinationGroup.1.destination.2.url}} | * {{pw.workflow.destinationGroup.1.destination.2.name}}*>","type": "mrkdwn"}},{"text": {"type": "mrkdwn","text": "<{{pw.workflow.destinationGroup.1.destination.3.url}} | * {{pw.workflow.destinationGroup.1.destination.3.name}}*>"},"type": "section"},{"type": "section","text": {"text": "<{{pw.workflow.destinationGroup.1.destination.4.url}} | * {{pw.workflow.destinationGroup.1.destination.4.name}}*>","type": "mrkdwn"}},{"type": "section","text": {"type": "mrkdwn","text": "<{{pw.workflow.destinationGroup.1.destination.5.url}} | * {{pw.workflow.destinationGroup.1.destination.5.name}}*>"}},{"text": {"type": "mrkdwn","text": "<{{pw.workflow.destinationGroup.1.destination.6.url}} | * {{pw.workflow.destinationGroup.1.destination.6.name}}*>"},"type": "section"},{"type": "section","text": {"type": "mrkdwn","text": "<{{pw.workflow.destinationGroup.1.destination.7.url}} | * {{pw.workflow.destinationGroup.1.destination.7.name}}*>"}},{"type": "section","text": {"type": "mrkdwn","text": "<{{pw.workflow.destinationGroup.1.destination.8.url}} | * {{pw.workflow.destinationGroup.1.destination.8.name}}*>"}},{"type": "section","text": {"type": "mrkdwn","text": "<{{pw.workflow.destinationGroup.1.destination.9.url}} | * {{pw.workflow.destinationGroup.1.destination.9.name}}*>"}},{"type": "header","text": {"emoji": true,"text": "{{pw.workflow.destinationGroup.2.name}}","type": "plain_text"}},{"type": "divider"},{"text": {"type": "mrkdwn","text": "<{{pw.workflow.destinationGroup.2.destination.0.url}} | * {{pw.workflow.destinationGroup.2.destination.0.name}}*>"},"type": "section"},{"text": {"type": "plain_text","text": "{{pw.workflow.destinationGroup.3.name}}","emoji": true},"type": "header"},{"type": "divider"},{"text": {"type": "mrkdwn","text": "<{{pw.workflow.destinationGroup.3.destination.0.url}} | * {{pw.workflow.destinationGroup.3.destination.0.name}}*>"},"type": "section"},{"type": "section","text": {"text": "<{{pw.workflow.destinationGroup.3.destination.1.url}} | * {{pw.workflow.destinationGroup.3.destination.1.name}}*>","type": "mrkdwn"}},{"text": {"text": "<{{pw.workflow.destinationGroup.3.destination.2.url}} | * {{pw.workflow.destinationGroup.3.destination.2.name}}*>","type": "mrkdwn"},"type": "section"},{"type": "header","text": {"emoji": true,"type": "plain_text","text": "{{pw.workflow.destinationGroup.4.name}}"}},{"type": "divider"},{"type": "section","text": {"type": "mrkdwn","text": "<{{pw.workflow.destinationGroup.4.destination.0.url}} | * {{pw.workflow.destinationGroup.4.destination.0.name}}*>"}},{"text": {"text": "<{{pw.workflow.destinationGroup.4.destination.1.url}} | * {{pw.workflow.destinationGroup.4.destination.1.name}}*>","type": "mrkdwn"},"type": "section"},{"text": {"text": "<{{pw.workflow.destinationGroup.4.destination.2.url}} | * {{pw.workflow.destinationGroup.4.destination.2.name}}*>","type": "mrkdwn"},"type": "section"},{"type": "section","text": {"text": "<{{pw.workflow.destinationGroup.4.destination.3.url}} | * {{pw.workflow.destinationGroup.4.destination.3.name}}*>","type": "mrkdwn"}},{"type": "header","text": {"type": "plain_text","text": ":camera: Snapshots","emoji": true}},{"type": "divider"},{"type": "section","text": {"type": "mrkdwn","text": "<{{pw.workflow.destinationGroup.1.destination.0.snapshot.protectedUrl}} | *High-Resolution Image: {{pw.workflow.destinationGroup.1.destination.0.name}}*>"}},{"type": "image","title": {"type": "plain_text","emoji": true,"text": "{{pw.workflow.destinationGroup.1.destination.0.name}}"},"alt_text": "{{pw.workflow.destinationGroup.1.destination.0.name}}","image_url": "{{pw.workflow.destinationGroup.1.destination.0.snapshot.publicUrl}}"},{"type": "section","text": {"text": "<{{pw.workflow.destinationGroup.1.destination.3.snapshot.protectedUrl}} | *High-Resolution Image: {{pw.workflow.destinationGroup.1.destination.3.name}}*>","type": "mrkdwn"}},{"title": {"emoji": true,"text": "{{pw.workflow.destinationGroup.1.destination.3.name}}","type": "plain_text"},"alt_text": "{{pw.workflow.destinationGroup.1.destination.3.name}}","type": "image","image_url": "{{pw.workflow.destinationGroup.1.destination.3.snapshot.publicUrl}}"}]} ]}
Rayon Hunte
  • 102
  • 1
  • 1
  • 9
  • Please elaborate on "maintain order" and share some of the code that loads the JSON from the API and loads it into the DIV. – Kostas Minaidis Oct 04 '22 at 22:05
  • @KostasMinaidis the setSelectedJSON updated the state and that renders the JSON string in the div. by the order I mean it has blocks and attachments I want to load the blocks or attachments first always. it's a find of Slack template builder. – Rayon Hunte Oct 04 '22 at 22:13
  • And what about "random order"? What exactly do you mean by that? – Kostas Minaidis Oct 04 '22 at 22:16
  • When the template loads it sometimes loads the attachments first and sometimes the blocks. I want it to always load the blocks or the attachments. I will add a sample of the JSON to the question. – Rayon Hunte Oct 04 '22 at 22:21
  • So your issue is property orderings inside an object type? Then you want something like [this](https://stackoverflow.com/a/53593328/2887218). Does that meet your needs? Or are you looking for something else – jcalz Oct 04 '22 at 22:56
  • @jcalz this was helpful, I used ``` const replacer = (key, value) => value instanceof Object && !(value instanceof Array) ? Object.keys(value) .sort() .reduce((sorted, key) => { sorted[key] = value[key]; return sorted }, {}) : value; ``` seems to be working, thanks – Rayon Hunte Oct 04 '22 at 23:38

0 Answers0