skip to Main Content

I have JSON:

{
  "entities": {},
  "intents": [],
  "speech": {
    "confidence": 0.4471,
    "tokens": [
      {
        "confidence": 0.4471,
        "end": 1560,
        "start": 560,
        "token": "Кот"
      }
    ]
  },
  "text": "Кот",
  "traits": {}
}
{
  "entities": {},
  "intents": [],
  "is_final": true,
  "speech": {
    "confidence": 0.4471,
    "tokens": [
      {
        "confidence": 0.4471,
        "end": 1560,
        "start": 560,
        "token": "Кот"
      }
    ]
  },
  "text": "Cat",
  "traits": {}
}

How to get last object? This is an example, I should have a lot of this objects
I want to have "Cat" from last object, how can I do it? without libraries.

3

Answers


  1. First of all, the JSON is not following the proper semantics, like how can two objects exist in a single JSON without any comma separation?
    Assuming, that you are getting an array of these objects, you can simply use the "find()" function to get the object which satisfies the condition. Lets assume the name of the array is "arr" and I am storing the result in "res":

    let res = arr.find(ele => ele.text === "Cat");
    

    For fetching last object in any array, you can use:

    1. the length property like res = arr[arr.length - 1];
    2. the slice method like res = arr.slice(-1);
    3. the pop method like res = arr.pop();

    Follow the below link for more information:
    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find

    Login or Signup to reply.
  2. It looks like your "JSON" has been created by appending JSON representations of individual objects, rather than pushing those objects to an array and then returning the JSON representation of that. You should get that software fixed to return valid JSON, but in the interim you can work around the problem by making the string into a JSON representation of an array of objects by adding [ and ] around it, and replacing occurrences of }{ with },{. You can then parse it successfully and return the text property of the last object in the array:

    jstr = `{
      "entities": {},
      "intents": [],
      "speech": {
        "confidence": 0.4471,
        "tokens": [
          {
            "confidence": 0.4471,
            "end": 1560,
            "start": 560,
            "token": "Кот"
          }
        ]
      },
      "text": "Кот",
      "traits": {}
    }
    {
      "entities": {},
      "intents": [],
      "is_final": true,
      "speech": {
        "confidence": 0.4471,
        "tokens": [
          {
            "confidence": 0.4471,
            "end": 1560,
            "start": 560,
            "token": "Кот"
          }
        ]
      },
      "text": "Cat",
      "traits": {}
    }`
    
    jstr = '[' + jstr.replace(/}s*{/, '},{') + ']'
    
    arr = JSON.parse(jstr)
    console.log(arr[arr.length-1].text)
    Login or Signup to reply.
  3. Assuming the separator between each objects might or might not have whitespaces and/or newlines, you can parse the JSON manually instead following the JSON specification here (but with a slight modification of ignoring the ending comma when the depth is 0 – top-level):

    function extractJSONWithoutComma(input) {
      const output = [];
    
      let startBoundary = 0;
      let depth = 0;
      let inQuote = false;
    
      // We don't count the depth of array here assuming the top-level is all objects
      // We didn't check the validity of the JSON here, just trying to find the separator
    
      for (let i = 0; i < input.length; i++) {
        const char = input[i];
    
        // The only key to end a quote is another "
        // The reason why we need to know is it inside a string or not is to prevent from { inside the string
        if (inQuote) {
          if (char === '\') {
            i++; // Skip one character
            continue;
          }
          if (char === '"') {
            inQuote = false;
          }
          continue;
        }
    
        switch (char) {
          case '{':
            if (depth === 0) startBoundary = i;
            depth++;
            break;
          case '}':
            depth--;
            // When depth matched 0, it means this is an object separator
            if (depth === 0) {
              output.push(JSON.parse(input.substring(startBoundary, i + 1)));
            }
            break;
          case '"':
            inQuote = true;
            break;
        }
      }
    
      return output;
    }
    
    const testCase1 = `{
      "entities": {},
      "intents": [],
      "speech": {
        "confidence": 0.4471,
        "tokens": [
          {
            "confidence": 0.4471,
            "end": 1560,
            "start": 560,
            "token": "Кот"
          }
        ]
      },
      "text": "Кот",
      "traits": {}
    }
    {
      "entities": {},
      "intents": [],
      "is_final": true,
      "speech": {
        "confidence": 0.4471,
        "tokens": [
          {
            "confidence": 0.4471,
            "end": 1560,
            "start": 560,
            "token": "Кот"
          }
        ]
      },
      "text": "Cat",
      "traits": {}
    }`;
    
    const testCase2 = '{"a":1}{"b":2}';
    const testCase3 = '{"a":"{}}"}{"b":2}';
    const testCase4 = '{"a":"{}   {"}{"b":2}'; // The string inside a gets converted to },{ unexpectedly if using naive solution of replacing all `}s*{` to `},{`
    
    console.log(extractJSONWithoutComma(testCase1));
    console.log(extractJSONWithoutComma(testCase2));
    console.log(extractJSONWithoutComma(testCase3));
    console.log(extractJSONWithoutComma(testCase4));
    
    // And to get your last object:
    
    const result = extractJSONWithoutComma(testCase1);
    console.log(result[result.length - 1].text);
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search