title: Parsing Valid JSON with TJSONObject using Embarcadero Code Example fails with exception
body: <p>Here is the example code from the Embarcadero help (<a href="http://docwiki.embarcadero.com/RADStudio/Rio/en/JSON" rel="noreferrer">http://docwiki.embarcadero.com/RADStudio/Rio/en/JSON</a>):</p>
  
  <p>you can transform the JSON string representation into a JSON with one of the following code snippets.</p>
  
  <p>Using <strong>ParseJSONValue</strong>:</p>
  
  <pre class="lang-pascal prettyprint-override"><code>procedure ConsumeJsonString;
  var
    LJSONObject: TJSONObject;
  
  begin
  
    LJSONObject := nil;
    try
  
      { convert String to JSON }
      LJSONObject := TJSONObject.ParseJSONValue(TEncoding.ASCII.GetBytes(GJSONString), 0) as TJSONObject;
  
      { output the JSON to console as String }
      Writeln(LJSONObject.ToString);
    finally
      LJSONObject.Free;
    end;
  </code></pre>
  
  <p>That approach fails with a class invalid type cast on the as line !!</p>
  
  <p>Using <strong>Parse</strong>:</p>
  
  <pre class="lang-pascal prettyprint-override"><code>procedure ConsumeJsonBytes;
  var
    LJSONObject: TJSONObject;
  
  begin
    LJSONObject := nil;
    try
      LJSONObject := TJsonObject.Create;
      { convert String to JSON }
      LJSONObject.Parse(BytesOf(GJSONString), 0);
  
      { output the JSON to console as String }
      Writeln(LJSONObject.ToString);
    finally
      LJSONObject.Free;
    end;
  end;
  </code></pre>
  
  <p>In the Embarcadero example The input JSON is declared in code as a string:</p>
  
  <pre class="lang-pascal prettyprint-override"><code>  const
    GJSONString =
      '{' +
      '    "name": {'+
      '        "A JSON Object": {' +
      '          "id": "1"' +
      '        },' +
      '        "Another JSON Object": {' +
      '          "id": "2"' +
      '        }' +
      '    },' +
      '    "totalobjects": "2"' +
      '}';
  </code></pre>
  
  <p>The JSON I am processing is from BetFair. It is valid (verified with <a href="http://jsonformatter.curiousconcept.com/" rel="noreferrer">http://jsonformatter.curiousconcept.com/</a> and <a href="http://www.freeformatter.com/json-validator.html" rel="noreferrer">http://www.freeformatter.com/json-validator.html</a> and <a href="http://jsonlint.com/" rel="noreferrer">http://jsonlint.com/</a>):</p>
  
  <pre class="lang-json prettyprint-override"><code>[{
      "caption": "Get the number of soccer markets",
      "methodName": "SportsAPING/v1.0/listEventTypes",
      "params": {
          "filter": {
              "eventTypeIds": [
                  1
              ]
          }
      }
  },
  {
          "caption": "Get the next horse race in the UK",
          "methodName": "SportsAPING/v1.0/listMarketCatalogue",
          "params": {
              "filter": {
                  "eventTypeIds": [
                      7
                  ],
                  "marketCountries": [
                      "GB"
                  ],
                  "marketTypeCodes": [
                      "WIN"
                  ],
                  "marketStartTime": {
                      "from": "2013-04-11T11:03:36Z"
                  }
              },
              "sort": "FIRST_TO_START",
              "maxResults": "1",
              "marketProjection": [
                  "COMPETITION",
                  "EVENT",
                  "EVENT_TYPE",
                  "MARKET_DESCRIPTION",
                  "RUNNER_DESCRIPTION"
              ]
          }
  },
  {
          "caption": "Get the 2 best prices, rolled up to £10 for the London Mayor Election 2016",
          "methodName": "SportsAPING/v1.0/listMarketBook",
          "params": {
              "marketIds": [
                  "1.107728324"
              ],
              "priceProjection": {
                  "priceData": [
                      "EX_BEST_OFFERS"
                  ],
                  "exBestOffersOverrides": {
                      "bestPricesDepth": "2",
                      "rollupModel": "STAKE",
                      "rollupLimit": "10"
                  }
              }
          }
  },
  {
          "caption": "Get my current unmatched bets",
          "methodName": "SportsAPING/v1.0/listCurrentOrders",
          "params": {
              "orderProjection": "EXECUTABLE"
          }
  },
  {
          "caption": "Get my application keys",
          "methodName": "AccountAPING/v1.0/getDeveloperAppKeys",
          "params": {
          }
  }]
  </code></pre>
  
  <p>I am not declaring this as a string, but reading it from file thus:</p>
  
  <pre class="lang-pascal prettyprint-override"><code>TFile.ReadAllText(aFileName);
  </code></pre>
  
  <p>The file read is successfully.</p>
  
  <p>Here is the code that causes the problem. I have used approach 2 as recommended from Embarcadero docs as in line above. That failed. I split the approach across more variables for debugging purposes. </p>
  
  <p>According to the Embarcadero docs vParseResult will be a negative
  value if parsing fails for any reason. It does not. However, vJSONPair ends up nil even though the parse succeeds (second line after the try) which leads to an exception:</p>
  
  <pre class="lang-pascal prettyprint-override"><code>procedure TfMain.loadScenarioData(aFilename: string);
  var
    vJSONString: string;
    vJSONScenario: TJSONObject;
    vJSONPair: TJSONPair;
    vJSONScenarioEntry: TJSONValue;
    vJSONScenarioValue: string;
    I: Int16;
    vParseResult: Integer;
  begin
    vJSONString := TFile.ReadAllText(aFileName);
  
    vJSONScenario := nil;
  
    try
    vJSONScenario := TJSONObject.Create;
    vParseResult := vJSONScenario.Parse(BytesOf(vJSONString),0);
    if  vParseResult &gt;= 0 then
    begin
        //BetFair Specific 'caption' key
        vJSONPair := vJSONScenario.Get('caption');
        vJSONScenarioEntry := vJSONPair.JsonValue;
        vJSONScenarioValue := vJSONScenarioEntry.Value;
        cbScenario.Items.Add(vJSONScenarioValue);
    end;
  
    finally
        vJSONScenario.Free;
  
    end;
  end;
  </code></pre>
  
  <p>This kind of thing where there is not adequate documentation for the IDE and language or where the documentation is not complete or adequate - is a terrible waste of time and gives me problems with completing work. I need to be solving problems using the language and libraries, not solving problems with them or more to the point with inadequate, ambiguous, and hard to find documentation.</p>