【问题标题】:Parse Nested JSON File in C++Builder在 C++Builder 中解析嵌套的 JSON 文件
【发布时间】:2021-05-20 00:39:21
【问题描述】:

我正在使用带有 64 位编译器的 C++Builder 10.4.2。我正在尝试解析下面的嵌套 JSON 文件,以便 "US.NYSE" 值位于 TJSONArray 中,然后遍历它们以获取每个数组值。我的代码没有将 "US.NYSE" 放入数组中。你能展示如何将"US.NYSE" 放入TJSONArray 中吗?目前,我无法测试for 循环,这个for 循环设置正确吗?

{
  "data":{
    "US.NYSE":{
      "fin_id":"US.NYSE",
      "exchange":"New York Stock Exchange",
      "market":"Canonical",
      "products":null,
      "local_time":"2020-11-27T11:55:00-05:00",
      "status":"Open",
      "reason":"Market Holiday - Primary Trading Session (Partial)",
      "until":"2020-11-27T12:45:00-05:00",
      "next_bell":"2020-11-27T13:00:00-05:00"
    }
  }
}
void __fastcall TForm1::Button33Click(TObject *Sender)
{

    UnicodeString s1, s2, s3, s4, s5, s6, s7, s8, s9;

    std::unique_ptr<TStringStream> jsonstream(new TStringStream);
    jsonstream->LoadFromFile("marketstatus1.json");

    TJSONObject* MyjsonFile = (TJSONObject*)TJSONObject::ParseJSONValue(jsonstream->DataString);
    Application->MessageBoxW(MyjsonFile->ToString().w_str(), L"", 0);

    TJSONArray* MyjsonArray = (TJSONArray*)TJSONObject::ParseJSONValue(MyjsonFile->GetValue("data")->ToString());
    Application->MessageBoxW(MyjsonArray->ToString().w_str(), L"", 0);


    int TestCount = MyjsonArray->Count;

    for(int i=0; i<MyjsonArray->Count; i++){
        s1 = MyjsonArray->Items[i]->GetValue<UnicodeString>("fin_id");
        s2 = MyjsonArray->Items[i]->GetValue<UnicodeString>("exchange");
        s3 = MyjsonArray->Items[i]->GetValue<UnicodeString>("market");
        s4 = MyjsonArray->Items[i]->GetValue<UnicodeString>("products");
        s5 = MyjsonArray->Items[i]->GetValue<UnicodeString>("local_time");
        s6 = MyjsonArray->Items[i]->GetValue<UnicodeString>("status");
        s7 = MyjsonArray->Items[i]->GetValue<UnicodeString>("reason");
        s8 = MyjsonArray->Items[i]->GetValue<UnicodeString>("until");
        s9 = MyjsonArray->Items[i]->GetValue<UnicodeString>("next_bell");
    }

}

编辑

this answer 中发布的代码有效,GetValue() 方法除外:

s1 = MyjsonStock->GetValue<UnicodeString>(_D("fin_id"));

这会在ustring.h 文件中给出错误:

'UnicodeString' 不引用值

此错误跳转到ustring.hUnicodeString 类的第28 行。我添加了这个文件的顶部,显示了下面的第 28 行。您能否建议更改 GetValue() 方法的调用?

namespace System
{
  class                  TVarRec;
  class RTL_DELPHIRETURN Currency;
#if !defined(_DELPHI_NEXTGEN)
  class RTL_DELPHIRETURN WideString;
#endif
    
  /////////////////////////////////////////////////////////////////////////////
  // UnicodeString: String class compatible with Delphi's Native 'string' type
  /////////////////////////////////////////////////////////////////////////////
  class RTL_DELPHIRETURN UnicodeString  //ERROR JUMPS HERE LINE(28)
  {
    friend UnicodeString operator +(const char*, const UnicodeString& rhs);
    friend UnicodeString operator +(const wchar_t*, const UnicodeString& rhs);
    friend UnicodeString operator +(const char16_t*, const UnicodeString& rhs);
    friend UnicodeString operator +(const char32_t*, const UnicodeString& rhs);

  public:

【问题讨论】:

    标签: json c++builder


    【解决方案1】:

    您对 JSON 的工作原理存在误解。我建议您查看https://www.json.org 提供的 JSON 标准定义的语法。

    您显示的 JSON 中没有没有数组。数组用[] 括号表示。对象用{} 大括号表示。因此,顶级 JSON 值是对象,"data“ 值是对象,"US.NYSE" 是对象。因此,2 个ParseJSONValue() 调用都将返回TJSONObject,而不是TJSONArray

    不需要第二次调用ParseJSONValue(),因为那些内部TJSONObjects 已经被第一次ParseJSONValue() 调用解析并且可以在MyjsonFile 的值层次结构内访问。访问这些值时,只需将 GetValue() 的返回值类型转换为 TJSONObject*

    另外,您需要delete ParseJSONValue() 返回的值以避免内存泄漏。

    试试这个:

    void __fastcall TForm1::Button33Click(TObject *Sender)
    {
      UnicodeString s1, s2, s3, s4, s5, s6, s7, s8, s9;
    
      std::unique_ptr<TStringStream> jsonstream(new TStringStream);
      jsonstream->LoadFromFile(_D("marketstatus1.json"));
    
      std::unique_ptr<TJSONValue> MyjsonValue = TJSONObject::ParseJSONValue(jsonstream->DataString);
    
      TJSONObject* MyjsonFile = static_cast<TJSONObject*>(MyjsonValue.get());
      Application->MessageBoxW(MyjsonFile->ToString().c_str(), _D(""), 0);
    
      TJSONObject* MyjsonData = static_cast<TJSONObject*>(MyjsonFile->GetValue(_D("data")));
      Application->MessageBoxW(MyjsonData->ToString().c_str(), _D(""), 0);
    
      TJSONObject* MyjsonStock = static_cast<TJSONObject*>(MyjsonData->GetValue(_D("US.NYSE")));
    
      s1 = MyjsonStock->GetValue(_D("fin_id"))->Value();
      s2 = MyjsonStock->GetValue(_D("exchange"))->Value();
      s3 = MyjsonStock->GetValue(_D("market"))->Value();
      s4 = MyjsonStock->GetValue(_D("products"))->Value();
      s5 = MyjsonStock->GetValue(_D("local_time"))->Value();
      s6 = MyjsonStock->GetValue(_D("status"))->Value();
      s7 = MyjsonStock->GetValue(_D("reason"))->Value();
      s8 = MyjsonStock->GetValue(_D("until"))->Value();
      s9 = MyjsonStock->GetValue(_D("next_bell"))->Value();
    }
    

    【讨论】:

    • 除了调用 GetValue 方法外,您发布的代码都可以正常工作。我编辑了上面的原始问题以添加所需的信息。您能否建议对 GetValue 调用进行更改。谢谢。
    • 代码看起来不错,基于documentation。但老实说,我从不使用GetValue() 的模板版本,我只会使用non-templated version。我已经更新了我的答案以显示这一点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多