Json文件读写

本文主要介绍UE4下的JSON文件的读写

文件读写

首先我们需要扩展普通的文件读写方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
bool UTestLib::V_LoadStringFromFile(const FString& FileName, const FString& RelativePath, FString& result)
{
if (!FileName.IsEmpty())
{
FString file=FPaths::ProjectContentDir()+RelativePath+FileName;
return FFileHelper::LoadFileToString(result,*file);

}
return false;
}
bool UTestLib::V_SaveStringToFile(const FString& FileName, const FString& RelativePath, const FString& string)
{

if (!FileName.IsEmpty())
{
FString file = FPaths::ProjectContentDir() + RelativePath + FileName;
return FFileHelper::SaveStringToFile(string,*file);

}
return false;
}

此方法是以工程目录下的Content路径为基础的,如果需要指定其他路径就需要替换 FPaths::ProjectContentDir()方法或者干脆直接把整个路径给公开

JSON文件读写

先来一个示例JSON文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
{
"school": "Super",
"name":
[
"Tom",
"Jien",
"Harry"
],
"Tom":
{
"sex":"boy",
"score":
{
"Math":99,
"English":80
}
},
"Jien":
{
"sex":"boy",
"score":
{
"Math":88,
"English":95
}
}
}

解释几个关键参数

  • TJsonReader
1
2
TSharedPtr<FJsonObject> JSONContentObject;
TSharedRef<TJsonReader<TCHAR>> Reader = TJsonReaderFactory<TCHAR>::Create(JSONInput);

用来反序列化的一个类,把文件中的字符串先存放到TJsonReader的智能指针里;同样的还有写入操作和序列化操作,对应的类就是TJsonWriter

  • FJsonObject
1
FJsonSerializer::Deserialize(Reader, JSONContentObject)

通过FJsonSerializerTJsonReader 反序列化到FJsonObject中,然后就可以通过方法来解读

1
StringValue=JSONContentObject->GetStringField(key);

当然,有个前提是这个key对应的一个值,如示例中的"school": "Super

  • FJsonValue

因为JSON文件是可以使用数组和嵌套的,对于数组,就必须用到FJsonValue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/*
"name":
[
"Tom",
"Jien",
"Harry"
],
*/

TArray<TSharedPtr<FJsonValue>> JsonParedValue;
TSharedPtr<FJsonObject> JsonObj;
if (FJsonSerializer::Deserialize(JsonReader, JsonObj))
{
JsonParedValue = JsonObj->GetArrayField(key);
}

因为name对应的是一个数组,所以得到的FJsonValue就是这个数组的成员

然后通过下面方法得到所有成员

1
2
3
4
for (auto i: JsonParedValue)
{
value.Add(i->AsString());
}

完整的解析一个键值对,值是数组的方法如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
bool UTestLib::V_LoadValueArrayFromJsonKey(const FString& JsonString, const FString& key, TArray<FString>& value)
{
TArray<TSharedPtr<FJsonValue>> JsonParedValue;
TSharedPtr<FJsonObject> JsonObj;
TSharedRef<TJsonReader<TCHAR>> JsonReader = TJsonReaderFactory<TCHAR>::Create(JsonString);
if (FJsonSerializer::Deserialize(JsonReader, JsonObj))
{
JsonParedValue = JsonObj->GetArrayField(key);

for (auto i: JsonParedValue)
{
value.Add(i->AsString());
}
return true;
}
return false;
}

简单的键值对的方法如下

1
2
3
4
5
6
7
8
9
10
11
12
bool UTestLib::V_LoadValueFromJsonKey(const FString& JsonString, const FString& key, FString& value)
{
TArray<TSharedPtr<FJsonValue>> JsonParedValue;
TSharedPtr<FJsonObject> JsonObj;
TSharedRef<TJsonReader<TCHAR>> JsonReader=TJsonReaderFactory<TCHAR>::Create(JsonString);
if (FJsonSerializer::Deserialize(JsonReader, JsonObj))
{
value=JsonObj->GetStringField(key);
return true;
}
return false;
}

写入会麻烦一点,首先需要些一个函数来把FJsonObject转换为FString

1
2
3
4
5
6
7
8
9
10
bool UTestLib::GetStringFromJsonObj(const TSharedPtr<FJsonObject>& InJsonObj, FString& OutStr)
{
if (InJsonObj.IsValid() && InJsonObj->Values.Num() > 0)
{
TSharedRef<TJsonWriter<TCHAR>> t_writer = TJsonWriterFactory<>::Create(&OutStr);
FJsonSerializer::Serialize(InJsonObj.ToSharedRef(), t_writer);
return true;
}
return false;
}

然后我们直接写一个改写固定键值对的函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
bool UTestLib::V_SaveJsonData(const FString& FileName, const FString& RelativePath, const FString& key, const FString& value)
{
FString JsonString;
FString result;
if (V_LoadStringFromFile(FileName, RelativePath, JsonString))
{
TArray<TSharedPtr<FJsonValue>> JsonParedValue;
TSharedPtr<FJsonObject> JsonObj;
TSharedRef<TJsonReader<TCHAR>> JsonReader = TJsonReaderFactory<TCHAR>::Create(JsonString);
if (FJsonSerializer::Deserialize(JsonReader, JsonObj))
{
JsonObj->SetStringField(key,value);
if (GetStringFromJsonObj(JsonObj, result))
{
return V_SaveStringToFile(FileName, RelativePath, result);
}
}
}
return false;

}

最后得到结果

1
2
3
4
5
6
7
8
9
10
11

\
{
"school": "hello",
"name": [
"Tom",
"Jien",
"Harry"
],
"Tom":..........
}