【问题标题】:C++ Nested JSON in Unreal Engine 4虚幻引擎 4 中的 C++ 嵌套 JSON
【发布时间】:2015-08-01 06:36:19
【问题描述】:

我有一个从服务器获取的 JSON 对象,看起来像这样:

{
    "state":"1",
    "player1": {
        "alias":"Player Name",
        "ready":"0"
    }
}

我能够获取 JSON,将其解析为 FJsonObject,并使用以下代码检索 JSON 对象的第一级中的任何数字或字符串以进行序列化:

TSharedPtr<FJsonObject> JsonParsed;
TSharedRef<TJsonReader<TCHAR>> JsonReader = TJsonReaderFactory<TCHAR>::Create(json);
if (FJsonSerializer::Deserialize(JsonReader, JsonParsed))
    //Use JsonParsed

这段代码读取字符串:

FString AJSONContainer::getStringWithKey(FString key)
{
    return storedJSON->GetStringField(key);
}    

旁注:

AJSONContainer 只是一个 Actor 类,我用来从蓝图中调用这些函数。


这一切都很好,花花公子,但是当我尝试从第二层阅读内容时,事情就不起作用了。

我写了这段代码来下一个层次:

TSharedPtr<FJsonObject> nested = storedJSON->GetObjectField(key);

但是所有获取nested 字段的调用都没有返回任何内容。

nested->GetStringField(anotherKey); //Nothing

所以,例如,对于上面的 JSON,这个:

TSharedPtr<FJsonObject> nested = storedJSON->GetObjectField("player1");
FString alias = nested->GetStringField("alias");

alias 打印到控制台时没有任何价值。


我做错了吗?为什么二级 JSON 不起作用?

【问题讨论】:

  • 调用GetField&lt;EJson::Object&gt; 而不是GetObjectField 可以轻松解决问题。它会给你一个JsonValue,你可以用FJsonValue::AsObject方法转换成FJsonValue

标签: c++ json unreal-engine4


【解决方案1】:

不知道你是否把它整理好,但我发现了一个非常讨厌的函数,它适用于嵌套对象,也适用于数组。它为您提供了一个 USTRUCT,因此您不必使用通过键获取值的函数(我不喜欢它们,因为它们很容易出错)。相反,您将拥有类型安全性!

FJsonObjectConverter::JsonObjectStringToUStruct

这是docsUE4 AnswerHub 上回答的另一个问题

基本上,您创建目标 USTRUCT(或嵌套 JSON 的 USTRUCT),用 UPROPERTY 标记所有属性,以便 Unreal 知道它们的名称,然后使用此函数。它将通过匹配来复制这些值。它甚至复制数组! =D

示例

我将调用 JSON FString 进行反序列化Json,它的结构如下所示。它包含一个嵌套对象和一个数组,让事情变得有趣。

{
    "nested" : {
        "id" : "654asdf",
        "name" : "The Name"
    },
    "foo" : "foobar",
    "bar_arr" : [
        { "barfoo" : "asdf" },
        { "barfoo" : "qwer" }
    ]
}

在转换之前,我们需要从内到外创建 USTRUCT(这样我们就可以在外部引用内部)。请记住始终使用 F 作为结构名称。

USTRUCT()
struct FNested
{
    GENERATED_USTRUCT_BODY()

    UPROPERTY()
    FString id;

    UPROPERTY()
    FString name;
};

USTRUCT()
struct FBar
{
    GENERATED_USTRUCT_BODY()

    UPROPERTY()
    FString barfoo;
};

USTRUCT()
struct FJsonData
{
    GENERATED_USTRUCT_BODY()

    UPROPERTY()
    FNested nested;

    UPROPERTY()
    FString foo;

    UPROPERTY()
    TArray<FBar> bar_arr;
};

转换过程如下:

FJsonData JsonData;
FJsonObjectConverter::JsonObjectStringToUStruct<FJsonData>(
    Json,
    &JsonData,
    0, 0);

现在,您可以像在标准 C++ 结构中一样访问所有属性。例如,访问 barfoo 之一:

FString barfoo0 = JsonData.bar_arr[0].barfoo;

我没有在 JSON 中使用 int 和 float 对其进行测试,但由于它甚至复制数组,我相信这也可以。

【讨论】:

    【解决方案2】:
        for (auto currJsonValue = JsonObject->Values.CreateConstIterator(); currJsonValue; ++currJsonValue)
        {
            // Get the key name
            const FString Name = (*currJsonValue).Key;
    
            // Get the value as a FJsonValue object
            TSharedPtr< FJsonValue > Value = (*currJsonValue).Value;
    
            TSharedPtr<FJsonObject> JsonObjectIn = Value->AsObject();
        }
    

    嵌套的Json Object可以通过GetObjectField或者我贴的代码来访问。

    【讨论】:

      【解决方案3】:

      正如我评论的那样,调用GetField&lt;EJson::Object&gt; 而不是GetObjectField 是解决方案。

      所以这段代码会得到你的嵌套 json:

      TSharedPtr<FJsonValue> nested = storedJSON->GetField<EJson::Object>("player1");
      TSharedPtr<FJsonObject> nestedParsed = nested->AsObject();
      FString alias = nestedParsed->GetStringField("alias"); // alias == "Player Name"
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-10-12
        • 2015-01-13
        • 1970-01-01
        • 2020-07-24
        • 2015-02-04
        • 2019-12-09
        • 2023-03-28
        • 2019-11-11
        相关资源
        最近更新 更多