|
@@ -0,0 +1,251 @@
|
|
|
+#include "Config/JsonConfigParser.h"
|
|
|
+#include "Serialization/JsonReader.h"
|
|
|
+#include "Serialization/JsonSerializer.h"
|
|
|
+#include "JsonObjectConverter.h"
|
|
|
+#include "Misc/FileHelper.h"
|
|
|
+#include "Misc/Paths.h"
|
|
|
+
|
|
|
+bool JsonConfigParser::LoadConfig(const FString& FilePath)
|
|
|
+{
|
|
|
+ FString FileContent;
|
|
|
+ if (!FFileHelper::LoadFileToString(FileContent, *FilePath))
|
|
|
+ {
|
|
|
+ UE_LOG(LogTemp, Error, TEXT("Failed to load JSON file: %s"), *FilePath);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(FileContent);
|
|
|
+ if (!FJsonSerializer::Deserialize(Reader, ParsedData) || !ParsedData.IsValid())
|
|
|
+ {
|
|
|
+ UE_LOG(LogTemp, Error, TEXT("Failed to parse JSON file: %s"), *FilePath);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+FString JsonConfigParser::GetString(const FString& Key, const FString& DefaultValue) const
|
|
|
+{
|
|
|
+ TSharedPtr<FJsonValue> Value = FindJsonValue(Key);
|
|
|
+ if (Value.IsValid() && Value->Type == EJson::String)
|
|
|
+ {
|
|
|
+ return Value->AsString();
|
|
|
+ }
|
|
|
+ return DefaultValue;
|
|
|
+}
|
|
|
+
|
|
|
+int32 JsonConfigParser::GetInt(const FString& Key, int32 DefaultValue) const
|
|
|
+{
|
|
|
+ TSharedPtr<FJsonValue> Value = FindJsonValue(Key);
|
|
|
+ if (Value.IsValid() && Value->Type == EJson::Number)
|
|
|
+ {
|
|
|
+ return static_cast<int32>(Value->AsNumber());
|
|
|
+ }
|
|
|
+ return DefaultValue;
|
|
|
+}
|
|
|
+
|
|
|
+float JsonConfigParser::GetFloat(const FString& Key, float DefaultValue) const
|
|
|
+{
|
|
|
+ TSharedPtr<FJsonValue> Value = FindJsonValue(Key);
|
|
|
+ if (Value.IsValid() && Value->Type == EJson::Number)
|
|
|
+ {
|
|
|
+ return Value->AsNumber();
|
|
|
+ }
|
|
|
+ return DefaultValue;
|
|
|
+}
|
|
|
+
|
|
|
+bool JsonConfigParser::GetBool(const FString& Key, bool DefaultValue) const
|
|
|
+{
|
|
|
+ TSharedPtr<FJsonValue> Value = FindJsonValue(Key);
|
|
|
+ if (Value.IsValid() && Value->Type == EJson::Boolean)
|
|
|
+ {
|
|
|
+ return Value->AsBool();
|
|
|
+ }
|
|
|
+ return DefaultValue;
|
|
|
+}
|
|
|
+
|
|
|
+TArray<FString> JsonConfigParser::GetArray(const FString& Key) const
|
|
|
+{
|
|
|
+ TArray<FString> Result;
|
|
|
+ TSharedPtr<FJsonValue> Value = FindJsonValue(Key);
|
|
|
+ if (Value.IsValid() && Value->Type == EJson::Array)
|
|
|
+ {
|
|
|
+ for (const auto& ArrayValue : Value->AsArray())
|
|
|
+ {
|
|
|
+ Result.Add(ArrayValue->AsString());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return Result;
|
|
|
+}
|
|
|
+
|
|
|
+TSharedPtr<IConfigParser> JsonConfigParser::GetObject(const FString& Key) const
|
|
|
+{
|
|
|
+ TSharedPtr<FJsonValue> Value = FindJsonValue(Key);
|
|
|
+ if (Value.IsValid() && Value->Type == EJson::Object)
|
|
|
+ {
|
|
|
+ TSharedPtr<FJsonObject> SubObject = Value->AsObject();
|
|
|
+ TSharedPtr<JsonConfigParser> SubParser = MakeShareable(new JsonConfigParser());
|
|
|
+ SubParser->ParsedData = SubObject;
|
|
|
+ return SubParser;
|
|
|
+ }
|
|
|
+ return nullptr;
|
|
|
+}
|
|
|
+
|
|
|
+void JsonConfigParser::PrintConfig() const
|
|
|
+{
|
|
|
+ if (ParsedData.IsValid())
|
|
|
+ {
|
|
|
+ FString Output;
|
|
|
+ TSharedRef<TJsonWriter<>> Writer = TJsonWriterFactory<>::Create(&Output);
|
|
|
+ FJsonSerializer::Serialize(ParsedData.ToSharedRef(), Writer);
|
|
|
+ UE_LOG(LogTemp, Log, TEXT("JSON Config: %s"), *Output);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+TSharedPtr<FJsonValue> JsonConfigParser::FindJsonValue(const FString& Key) const
|
|
|
+{
|
|
|
+ if (!ParsedData.IsValid())
|
|
|
+ {
|
|
|
+ return nullptr;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理层次化键,支持 "Key.SubKey" 形式
|
|
|
+ TArray<FString> KeyParts;
|
|
|
+ Key.ParseIntoArray(KeyParts, TEXT("."));
|
|
|
+
|
|
|
+ TSharedPtr<FJsonObject> CurrentObject = ParsedData;
|
|
|
+ for (int32 i = 0; i < KeyParts.Num(); ++i)
|
|
|
+ {
|
|
|
+ if (CurrentObject.IsValid() && CurrentObject->HasField(KeyParts[i]))
|
|
|
+ {
|
|
|
+ if (i == KeyParts.Num() - 1)
|
|
|
+ {
|
|
|
+ return CurrentObject->TryGetField(KeyParts[i]);
|
|
|
+ }
|
|
|
+ CurrentObject = CurrentObject->GetObjectField(KeyParts[i]);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ return nullptr;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return nullptr;
|
|
|
+}
|
|
|
+
|
|
|
+template <typename StructType>
|
|
|
+bool JsonConfigParser::LoadStruct(const FString& FilePath, StructType& OutStruct)
|
|
|
+{
|
|
|
+ FString FileContent;
|
|
|
+ if (!FFileHelper::LoadFileToString(FileContent, *FilePath))
|
|
|
+ {
|
|
|
+ UE_LOG(LogTemp, Error, TEXT("Failed to load JSON file: %s"), *FilePath);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!FJsonObjectConverter::JsonObjectStringToUStruct(FileContent, &OutStruct, 0, 0))
|
|
|
+ {
|
|
|
+ UE_LOG(LogTemp, Error, TEXT("Failed to parse JSON into UStruct from file: %s"), *FilePath);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+template <typename StructType>
|
|
|
+bool JsonConfigParser::SaveStruct(const StructType& InStruct, const FString& FilePath)
|
|
|
+{
|
|
|
+ FString JsonString;
|
|
|
+ if (!FJsonObjectConverter::UStructToJsonObjectString(InStruct, JsonString))
|
|
|
+ {
|
|
|
+ UE_LOG(LogTemp, Error, TEXT("Failed to convert UStruct to JSON string."));
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!FFileHelper::SaveStringToFile(JsonString, *FilePath))
|
|
|
+ {
|
|
|
+ UE_LOG(LogTemp, Error, TEXT("Failed to save JSON to file: %s"), *FilePath);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+template <typename StructType>
|
|
|
+bool JsonConfigParser::LoadArrayStruct(const FString& FilePath, TArray<StructType>& OutArray)
|
|
|
+{
|
|
|
+ FString FileContent;
|
|
|
+ if (!FFileHelper::LoadFileToString(FileContent, *FilePath))
|
|
|
+ {
|
|
|
+ UE_LOG(LogTemp, Error, TEXT("Failed to load JSON file: %s"), *FilePath);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 解析 JSON 数组
|
|
|
+ TArray<TSharedPtr<FJsonValue>> JsonValues;
|
|
|
+ TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(FileContent);
|
|
|
+
|
|
|
+ if (!FJsonSerializer::Deserialize(Reader, JsonValues))
|
|
|
+ {
|
|
|
+ UE_LOG(LogTemp, Error, TEXT("Failed to parse JSON array: %s"), *FilePath);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 将 JSON 数组转换为 TArray<StructType>
|
|
|
+ for (const TSharedPtr<FJsonValue>& Value : JsonValues)
|
|
|
+ {
|
|
|
+ if (Value->Type == EJson::Object)
|
|
|
+ {
|
|
|
+ StructType StructData;
|
|
|
+ if (FJsonObjectConverter::JsonObjectToUStruct(Value->AsObject().ToSharedRef(), &StructData))
|
|
|
+ {
|
|
|
+ OutArray.Add(StructData);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ UE_LOG(LogTemp, Error, TEXT("Failed to convert JSON object to UStruct."));
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+template <typename StructType>
|
|
|
+bool JsonConfigParser::SaveArrayStruct(const TArray<StructType>& InArray, const FString& FilePath)
|
|
|
+{
|
|
|
+ // 构造 JSON 数组,每个元素对应一个 UStruct 转换后的 JSON 对象
|
|
|
+ TArray<TSharedPtr<FJsonValue>> JsonArray;
|
|
|
+
|
|
|
+ // 遍历并转换每一个结构体元素
|
|
|
+ for (const StructType& Element : InArray)
|
|
|
+ {
|
|
|
+ TSharedPtr<FJsonObject> JsonObject = MakeShareable(new FJsonObject());
|
|
|
+ if (!FJsonObjectConverter::UStructToJsonObject(StructType::StaticStruct(), &Element, JsonObject.ToSharedRef(), 0, 0))
|
|
|
+ {
|
|
|
+ UE_LOG(LogTemp, Error, TEXT("Failed to convert element to JSON object."));
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 将 JSON 对象包装为 JSON 值后加入数组中
|
|
|
+ JsonArray.Add(MakeShareable(new FJsonValueObject(JsonObject)));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 将 JSON 数组序列化为字符串
|
|
|
+ FString OutJsonString;
|
|
|
+ TSharedRef<TJsonWriter<>> Writer = TJsonWriterFactory<>::Create(&OutJsonString);
|
|
|
+ if (!FJsonSerializer::Serialize(JsonArray, Writer))
|
|
|
+ {
|
|
|
+ UE_LOG(LogTemp, Error, TEXT("Failed to serialize JSON array."));
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 保存 JSON 字符串到文件
|
|
|
+ if (!FFileHelper::SaveStringToFile(OutJsonString, *FilePath))
|
|
|
+ {
|
|
|
+ UE_LOG(LogTemp, Error, TEXT("Failed to save JSON to file: %s"), *FilePath);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|