A Demo Project for the UnrealEngineSDK
Loading...
Searching...
No Matches
DlgJsonWriter.cpp
Go to the documentation of this file.
1// Copyright Csaba Molnar, Daniel Butum. All Rights Reserved.
2#include "IO/DlgJsonWriter.h"
3
4#include "JsonObjectConverter.h"
5#include "JsonObjectWrapper.h"
6#include "Policies/CondensedJsonPrintPolicy.h"
7#include "UObject/UnrealType.h"
8#include "UObject/EnumProperty.h"
9#include "UObject/UObjectIterator.h"
10#include "UObject/TextProperty.h"
11#include "UObject/PropertyPortFlags.h"
12
13#include "DlgHelper.h"
14#include "NYReflectionHelper.h"
15
16DEFINE_LOG_CATEGORY(LogDlgJsonWriter);
17
19void FDlgJsonWriter::Write(const UStruct* StructDefinition, const void* ContainerPtr)
20{
21 DlgJsonWriterOptions WriterOptions;
22 WriterOptions.bPrettyPrint = true;
23 WriterOptions.InitialIndent = 0;
24 UStructToJsonString(StructDefinition, ContainerPtr, WriterOptions, JsonString);
25}
26
28TSharedPtr<FJsonValue> FDlgJsonWriter::ConvertScalarPropertyToJsonValue(const FNYProperty* Property, const void* const ContainerPtr, const void* const ValuePtr)
29{
30 check(Property);
31 if (bLogVerbose)
32 {
33 UE_LOG(LogDlgJsonWriter, Verbose, TEXT("ConvertScalarPropertyToJsonValue, Property = `%s`"), *Property->GetPathName());
34 }
35 if (ValuePtr == nullptr)
36 {
37 // Invalid
38 return MakeShared<FJsonValueNull>();
39 }
40
41 //
42 // NOTE: UProperty::ExportTextItem has the following arguments
43 // FString& ValueStr, const void* PropertyValue, const void* DefaultValue, UObject* Parent, int32 PortFlags, UObject* ExportRootScope
44 // We set the PropertyValue to be the same as DefaultValue, if DefaultValue is nullptr then this won't export the values different from default that the UProperty has.
45 // This is only a problem if the target class is different from default (like it happens in tests).
46 //
47
48 // Get Json String for Enum definition
49 auto GetJsonStringForEnum = [&ValuePtr](const UEnum* EnumDefinition, const FNYNumericProperty* NumericProperty) -> TSharedPtr<FJsonValue>
50 {
51 const FString StringValue = EnumDefinition->GetNameByIndex(NumericProperty->GetSignedIntPropertyValue(ValuePtr)).ToString();
52 return MakeShared<FJsonValueString>(StringValue);
53 };
54
55 // Add Index Metadata to JsonObject
56 auto AddIndexMetadata = [this, Property](TSharedRef<FJsonObject> JsonObject)
57 {
58 if (IndexInArray != INDEX_NONE && CanWriteIndex(Property))
59 {
60 JsonObject->SetField(TEXT("__index__"), MakeShared<FJsonValueNumber>(IndexInArray));
61 }
62 };
63
64 // Enum, export enums as strings
65 if (const auto* EnumProperty = FNYReflectionHelper::CastProperty<FNYEnumProperty>(Property))
66 {
67 return GetJsonStringForEnum(EnumProperty->GetEnum(), EnumProperty->GetUnderlyingProperty());
68 }
69
70 // Numeric, int, float, possible enum
71 if (const auto* NumericProperty = FNYReflectionHelper::CastProperty<FNYNumericProperty>(Property))
72 {
73 // See if it's an enum Numeric property
74 if (UEnum* EnumDef = NumericProperty->GetIntPropertyEnum())
75 {
76 return GetJsonStringForEnum(EnumDef, NumericProperty);
77 }
78
79 // We want to export numbers as numbers
80 if (NumericProperty->IsInteger())
81 {
83 {
84 // NOTE, because JSON only supports floats we do not use the FJsonValueNumber for map keys because integers
85 // are displayed as floats. For example '42' is displayed as '42.0'
86 // Instead we use it as a string, this should be similar as the parser can parse an int from string
87 return MakeShared<FJsonValueString>(FString::Printf(TEXT("%lld"), NumericProperty->GetSignedIntPropertyValue(ValuePtr)));
88 }
89
90 return MakeShared<FJsonValueNumber>(NumericProperty->GetSignedIntPropertyValue(ValuePtr));
91 }
92 if (NumericProperty->IsFloatingPoint())
93 {
94 return MakeShared<FJsonValueNumber>(NumericProperty->GetFloatingPointPropertyValue(ValuePtr));
95 }
96
97 // Invalid
98 return MakeShared<FJsonValueNull>();
99 }
100
101 // Bool, Export bools as JSON bools
102 if (const auto* BoolProperty = FNYReflectionHelper::CastProperty<FNYBoolProperty>(Property))
103 {
104 return MakeShared<FJsonValueBoolean>(BoolProperty->GetOptionalPropertyValue(ValuePtr));
105 }
106
107 // FString
108 if (const auto* StringProperty = FNYReflectionHelper::CastProperty<FNYStrProperty>(Property))
109 {
110 return MakeShared<FJsonValueString>(StringProperty->GetOptionalPropertyValue(ValuePtr));
111 }
112
113 // FName
114 if (const auto* NameProperty = FNYReflectionHelper::CastProperty<FNYNameProperty>(Property))
115 {
116 auto* NamePtr = static_cast<const FName*>(ValuePtr);
117 if (NamePtr == nullptr)
118 {
119 UE_LOG(LogDlgJsonWriter,
120 Error,
121 TEXT("Got Property = `%s` of type FNYNameProperty but the Value it not an FName"),
122 *NameProperty->GetName())
123 return MakeShared<FJsonValueNull>();
124 }
125 if (!NamePtr->IsValidIndexFast() || !NamePtr->IsValid())
126 {
127 UE_LOG(LogDlgJsonWriter, Error, TEXT("Got Property = `%s` of type FName but it is not valid :("), *NameProperty->GetNameCPP())
128 return MakeShared<FJsonValueNull>();
129 }
130 //check(NamePtr == NameProperty->GetPropertyValuePtr(Value));
131 return MakeShared<FJsonValueString>(NamePtr->ToString());
132 }
133
134 // FText
135 if (const auto* TextProperty = FNYReflectionHelper::CastProperty<FNYTextProperty>(Property))
136 {
137 return MakeShared<FJsonValueString>(TextProperty->GetOptionalPropertyValue(ValuePtr).ToString());
138 }
139
140 // TArray
141 if (const auto* ArrayProperty = FNYReflectionHelper::CastProperty<FNYArrayProperty>(Property))
142 {
143 TArray<TSharedPtr<FJsonValue>> Array;
144 const FDlgConstScriptArrayHelper Helper(ArrayProperty, ValuePtr);
145 for (int32 Index = 0, Num = Helper.Num(); Index < Num; Index++)
146 {
147 IndexInArray = Index;
148 TSharedPtr<FJsonValue> Elem = PropertyToJsonValue(ArrayProperty->Inner, ContainerPtr, Helper.GetConstRawPtr(Index));
149 if (Elem.IsValid())
150 {
151 // add to the array
152 Array.Push(Elem);
153 }
154 }
155
156 ResetState();
157 return MakeShared<FJsonValueArray>(Array);
158 }
159
160 // TSet
161 if (const auto* SetProperty = FNYReflectionHelper::CastProperty<FNYSetProperty>(Property))
162 {
163 TArray<TSharedPtr<FJsonValue>> Array;
164 const FScriptSetHelper Helper(SetProperty, ValuePtr);
165
166 // GetMaxIndex() instead of Num() - the container is not contiguous
167 // elements are in [0, GetMaxIndex[, some of them are invalid (Num() returns with the valid element num)
168 for (int32 Index = 0; Index < Helper.GetMaxIndex(); Index++)
169 {
170 if (!Helper.IsValidIndex(Index))
171 {
172 continue;
173 }
174
175 IndexInArray = Index;
176 TSharedPtr<FJsonValue> Elem = PropertyToJsonValue(SetProperty->ElementProp, ContainerPtr, Helper.GetElementPtr(Index));
177 if (Elem.IsValid())
178 {
179 // add to the array
180 Array.Push(Elem);
181 }
182 }
183
184 ResetState();
185 return MakeShared<FJsonValueArray>(Array);
186 }
187
188 // TMap
189 if (const auto* MapProperty = FNYReflectionHelper::CastProperty<FNYMapProperty>(Property))
190 {
191 const TSharedRef<FJsonObject> OutObject = MakeShared<FJsonObject>();
192 const FDlgConstScriptMapHelper Helper(MapProperty, ValuePtr);
193
194 // GetMaxIndex() instead of Num() - the container is not contiguous
195 // elements are in [0, GetMaxIndex[, some of them are invalid (Num() returns with the valid element num)
196 for (int32 Index = 0; Index < Helper.GetMaxIndex(); Index++)
197 {
198 if (!Helper.IsValidIndex(Index))
199 {
200 continue;
201 }
202 IndexInArray = Index;
203
204 bIsPropertyMapKey = true;
205 const uint8* MapKeyPtr = Helper.GetConstKeyPtr(Index);
206 const TSharedPtr<FJsonValue> KeyElement = PropertyToJsonValue(Helper.GetKeyProperty(), ContainerPtr, MapKeyPtr);
207
208 bIsPropertyMapKey = false;
209 const uint8* MapValuePtr = Helper.GetConstValuePtr(Index);
210 const TSharedPtr<FJsonValue> ValueElement = PropertyToJsonValue(Helper.GetValueProperty(), ContainerPtr, MapValuePtr);
211
212 if (KeyElement.IsValid() && ValueElement.IsValid())
213 {
214 check(MapKeyPtr);
215
216 FString KeyString;
217 if (auto* KeyStructProperty = FNYReflectionHelper::CastProperty<FNYStructProperty>(MapProperty->KeyProp))
218 {
219 // Key is a struct
220 MapProperty->KeyProp->ExportTextItem(KeyString, MapKeyPtr, MapKeyPtr, nullptr, PPF_None);
221 }
222 else
223 {
224 // Default to key string
225 KeyString = KeyElement->AsString();
226 }
227
228 // Fallback for anything else, what could this be :O
229 if (KeyString.IsEmpty())
230 {
231 MapProperty->KeyProp->ExportTextItem(KeyString, MapKeyPtr, MapKeyPtr, nullptr, PPF_None);
232
233 if (KeyString.IsEmpty())
234 {
235 UE_LOG(LogDlgJsonWriter, Error, TEXT("Unable to convert key to string for property `%s`."), *MapProperty->GetNameCPP())
236 KeyString = FString::Printf(TEXT("Unparsed Key %d"), Index);
237 }
238 }
239
240 OutObject->SetField(KeyString, ValueElement);
241 }
242 }
243
244 ResetState();
245 return MakeShared<FJsonValueObject>(OutObject);
246 }
247
248 // UStruct
249 if (const auto* StructProperty = FNYReflectionHelper::CastProperty<FNYStructProperty>(Property))
250 {
251 // Intentionally exclude the JSON Object wrapper, which specifically needs to export JSON in an object representation instead of a string
252 UScriptStruct::ICppStructOps* TheCppStructOps = StructProperty->Struct->GetCppStructOps();
253 if (StructProperty->Struct != FJsonObjectWrapper::StaticStruct() && TheCppStructOps && TheCppStructOps->HasExportTextItem())
254 {
255 // Export to native text
256 FString OutValueStr;
257 TheCppStructOps->ExportTextItem(OutValueStr, ValuePtr, ValuePtr, nullptr, PPF_None, nullptr);
258 return MakeShared<FJsonValueString>(OutValueStr);
259 }
260
261 // Handle Struct
262 TSharedRef<FJsonObject> OutObject = MakeShared<FJsonObject>();
263 AddIndexMetadata(OutObject);
264 if (UStructToJsonObject(StructProperty->Struct, ValuePtr, OutObject))
265 {
266 return MakeShared<FJsonValueObject>(OutObject);
267 }
268
269 // Invalid
270 return MakeShared<FJsonValueNull>();
271 }
272
273 // UObject
274 if (const auto* ObjectProperty = FNYReflectionHelper::CastProperty<FNYObjectProperty>(Property))
275 {
276 auto returnNullptr = [this, &ObjectProperty]() -> TSharedPtr<FJsonValue>
277 {
278 // Save reference as empty string
279 if (CanSaveAsReference(ObjectProperty, nullptr))
280 {
281 return MakeShared<FJsonValueString>(TEXT(""));
282 }
283
284 return MakeShared<FJsonValueNull>();
285 };
286
287 // NOTE: The ValuePtr here should be a pointer to a pointer
288 // Because the UObjects are pointers, we must deference it. So instead of it being a void** we want it to be a void*
289 const UObject* ObjectPtr = ObjectProperty->GetObjectPropertyValue_InContainer(ValuePtr);
290
291 // To find out if in nested containers the object is nullptr we must go a level up
292 const UObject* ContainerObjectPtr = ObjectProperty->GetObjectPropertyValue_InContainer(ContainerPtr);
293 if (ObjectPtr == nullptr || ContainerObjectPtr == nullptr)
294 {
295 // We can have nullptrs
296 if (bLogVerbose)
297 {
298 UE_LOG(
299 LogDlgJsonWriter,
300 Verbose,
301 TEXT("Property = `%s` Is a FNYObjectProperty but got null from ContainerPtrToValuePtr from it's StructObject (NOTE: UObjects can be nullptrs)"),
302 *Property->GetPathName()
303 );
304 }
305 return returnNullptr();
306 }
307 if (!ObjectPtr->IsValidLowLevelFast())
308 {
309 // Memory corruption?
310 UE_LOG(
311 LogDlgJsonWriter,
312 Error,
313 TEXT("ObjectPtr.IsValidLowLevelFast is false for Property = `%s`. Memory corruption for UObjects?"),
314 *Property->GetPathName()
315 );
316 return returnNullptr();
317 }
318
319 // Special case were we want just to save a reference to the object location
320 if (ObjectPtr != nullptr && CanSaveAsReference(ObjectProperty, ObjectPtr))
321 {
322 return MakeShared<FJsonValueString>(ObjectPtr->GetPathName());
323 }
324
325 // Save as normal JSON Object
326 TSharedRef<FJsonObject> OutObject = MakeShared<FJsonObject>();
327 AddIndexMetadata(OutObject);
328
329 // Set the uproperties of the object
330 const UClass* ObjectClass = ObjectProperty->PropertyClass;
331 if (UStructToJsonObject(ObjectClass, ObjectPtr, OutObject))
332 {
333 return MakeShared<FJsonValueObject>(OutObject);
334 }
335
336 // Invalid
337 return MakeShared<FJsonValueNull>();
338 }
339
340 // Default, convert to string
341 FString ValueString;
342 Property->ExportTextItem(ValueString, ValuePtr, ValuePtr, nullptr, PPF_None);
343 return MakeShared<FJsonValueString>(ValueString);
344}
345
347TSharedPtr<FJsonValue> FDlgJsonWriter::PropertyToJsonValue(const FNYProperty* Property, const void* const ContainerPtr, const void* const ValuePtr)
348{
349 check(Property);
350 if (bLogVerbose)
351 {
352 UE_LOG(LogDlgJsonWriter, Verbose, TEXT("PropertyToJsonValue, Property = `%s`"), *Property->GetPathName());
353 }
354
355 if (ContainerPtr == nullptr || ValuePtr == nullptr)
356 {
357 const auto* PropertyClass = Property->GetClass();
358 if (Property->IsA<FNYObjectProperty>())
359 {
360 // Object property, can be nullptr
361 if (bLogVerbose)
362 {
363 UE_LOG(
364 LogDlgJsonWriter,
365 Verbose,
366 TEXT("UStructToJsonObject - Unhandled property type Class = '%s', Name = `%s`. (NOTE: UObjects can be nullptrs)"),
367 *PropertyClass->GetName(), *Property->GetPathName()
368 );
369 }
370 }
371 else
372 {
373 UE_LOG(
374 LogDlgJsonWriter,
375 Error,
376 TEXT("UStructToJsonObject - Unhandled property type Class = '%s', Name = `%s`"),
377 *PropertyClass->GetName(), *Property->GetNameCPP()
378 );
379 }
380
381 return MakeShared<FJsonValueNull>();
382 }
383
384 // Scalar Only one property
385 if (Property->ArrayDim == 1)
386 {
387 return ConvertScalarPropertyToJsonValue(Property, ContainerPtr, ValuePtr);
388 }
389
390 // Array
391 // NOTE: we can't use here ArrayHelper, because then we might also need to use SetHelper, more code, meh
392 TArray<TSharedPtr<FJsonValue>> Array;
393 auto* ValueIntPtr = static_cast<const uint8*>(ValuePtr);
394 for (int Index = 0; Index < Property->ArrayDim; Index++)
395 {
396 IndexInArray = Index;
397
398 // ValuePtr + Index * Property->ElementSize is literally FScriptArrayHelper::GetRawPtr
399 const TSharedPtr<FJsonValue> JsonValue = ConvertScalarPropertyToJsonValue(Property, ContainerPtr, ValueIntPtr + Index * Property->ElementSize);
400 if (JsonValue.IsValid())
401 {
402 Array.Add(JsonValue);
403 }
404 }
405
406 ResetState();
407 return MakeShared<FJsonValueArray>(Array);
408}
409
411bool FDlgJsonWriter::UStructToJsonAttributes(const UStruct* StructDefinition, const void* const ContainerPtr, TMap<FString, TSharedPtr<FJsonValue>>& OutJsonAttributes)
412{
413 if (StructDefinition == nullptr || ContainerPtr == nullptr)
414 {
415 return false;
416 }
417 if (bLogVerbose)
418 {
419 UE_LOG(LogDlgJsonWriter, Verbose, TEXT("UStructToJsonAttributes, StructDefinition = `%s`"), *StructDefinition->GetPathName());
420 }
421
422 // Json Wrapper, already have an Object
423 if (StructDefinition == FJsonObjectWrapper::StaticStruct())
424 {
425 // Just copy it into the object
426 const FJsonObjectWrapper* ProxyObject = static_cast<const FJsonObjectWrapper*>(ContainerPtr);
427 if (ProxyObject->JsonObject.IsValid())
428 {
429 OutJsonAttributes = ProxyObject->JsonObject->Values;
430 }
431
432 return true;
433 }
434
435 // Handle UObject inheritance (children of class)
436 if (StructDefinition->IsA<UClass>())
437 {
438 const UObject* UnrealObject = static_cast<const UObject*>(ContainerPtr);
439 if (!UnrealObject->IsValidLowLevelFast())
440 {
441 UE_LOG(
442 LogDlgJsonWriter,
443 Error,
444 TEXT("UStructToJsonObject: StructDefinition = `%s` is a UClass and expected ContainerPtr to be an UObject. Memory corruption?"),
445 *StructDefinition->GetPathName()
446 );
447 return false;
448 }
449
450 // Write type, Objects because they can have inheritance
451 OutJsonAttributes.Add(TEXT("__type__"), MakeShared<FJsonValueString>(UnrealObject->GetClass()->GetName()));
452
453 // Structure points to the child
454 StructDefinition = UnrealObject->GetClass();
455 }
456 if (!StructDefinition->IsValidLowLevelFast())
457 {
458 UE_LOG(
459 LogDlgJsonWriter,
460 Error,
461 TEXT("UStructToJsonObject: StructDefinition = `%s` is a UClass and expected ContainerPtr.Class to be valid. Memory corruption?"),
462 *StructDefinition->GetPathName()
463 );
464 return false;
465 }
466
467 // Iterate over all the properties of the struct
468 for (TFieldIterator<const FNYProperty> It(StructDefinition); It; ++It)
469 {
470 const auto* Property = *It;
471 if (!ensure(Property))
472 continue;
473
474 // Check to see if we should ignore this property
475 if (CheckFlags != 0 && !Property->HasAnyPropertyFlags(CheckFlags))
476 {
477 // Property does not have the required Flags
478 if (bLogVerbose)
479 {
480 UE_LOG(LogDlgJsonWriter, Verbose, TEXT("Property = `%s` Does not have the required CheckFlags"), *Property->GetPathName());
481 }
482 continue;
483 }
484 if (CanSkipProperty(Property))
485 {
486 // Mark as skipped.
487 if (bLogVerbose)
488 {
489 UE_LOG(LogDlgJsonWriter, Verbose, TEXT("Property = `%s` Marked as skiped"), *Property->GetPathName());
490 }
491 continue;
492 }
493
494 // Get the Pointer to the Value
495 const void* ValuePtr = nullptr;
496 if (Property->IsA<FNYObjectProperty>())
497 {
498 // Handle pointers, only allowed to be UObjects (are already pointers to the Value)
499 ValuePtr = ContainerPtr;
500 }
501 else
502 {
503 // Normal non pointer property
504 ValuePtr = Property->ContainerPtrToValuePtr<void>(ContainerPtr, 0);
505 }
506
507 // convert the property to a FJsonValue
508 const TSharedPtr<FJsonValue> JsonValue = PropertyToJsonValue(Property, ContainerPtr, ValuePtr);
509 if (!JsonValue.IsValid())
510 {
511 const auto* PropertyClass = Property->GetClass();
512 if (Property->IsA<FNYObjectProperty>())
513 {
514 // Object property, can be nullptr
515 if (bLogVerbose)
516 {
517 UE_LOG(
518 LogDlgJsonWriter,
519 Verbose,
520 TEXT("UStructToJsonObject - Unhandled property, Class = `%s`, Name =`%s`, inside Struct = `%s`. (NOTE: UObjects can be nullptrs)"),
521 *PropertyClass->GetName(), *Property->GetPathName(), *StructDefinition->GetPathName()
522 );
523 }
524 }
525 else
526 {
527 UE_LOG(
528 LogDlgJsonWriter,
529 Warning,
530 TEXT("UStructToJsonObject - Unhandled property, Class = `%s`, Name =`%s`, inside Struct = `%s`"),
531 *PropertyClass->GetName(), *Property->GetPathName(), *StructDefinition->GetPathName()
532 );
533 }
534
535 continue;
536 }
537
538 // set the value on the output object
539 // NOTE default JSON writer makes the first letter to be lowercase, we do not want that ;) FJsonObjectConverter::StandardizeCase
540 const FString VariableName = Property->GetName();
541 OutJsonAttributes.Add(VariableName, JsonValue);
542 }
543
544 return true;
545}
546
548template<class CharType, class PrintPolicy>
549bool UStructToJsonStringInternal(const TSharedRef<FJsonObject>& JsonObject, const int32 InitialIndent, FString& OutJsonString)
550{
551 TSharedRef<TJsonWriter<CharType, PrintPolicy>> JsonWriter =
552 TJsonWriterFactory<CharType, PrintPolicy>::Create(&OutJsonString, InitialIndent);
553 const bool bSuccess = FJsonSerializer::Serialize(JsonObject, JsonWriter);
554 JsonWriter->Close();
555 return bSuccess;
556}
557
559bool FDlgJsonWriter::UStructToJsonString(const UStruct* StructDefinition, const void* const ContainerPtr,
560 const DlgJsonWriterOptions& Options, FString& OutJsonString)
561{
562 TSharedRef<FJsonObject> JsonObject = MakeShared<FJsonObject>();
563 if (UStructToJsonObject(StructDefinition, ContainerPtr, JsonObject))
564 {
565 bool bSuccess;
566 if (Options.bPrettyPrint)
567 {
568 bSuccess = UStructToJsonStringInternal<TCHAR, TPrettyJsonPrintPolicy<TCHAR>>(JsonObject, Options.InitialIndent, OutJsonString);
569 }
570 else
571 {
572 bSuccess = UStructToJsonStringInternal<TCHAR, TCondensedJsonPrintPolicy<TCHAR>>(JsonObject, Options.InitialIndent, OutJsonString);
573 }
574
575 if (bSuccess)
576 {
577 return true;
578 }
579 }
580
581 UE_LOG(LogDlgJsonWriter, Error, TEXT("UStructToJsonObjectString - Unable to write out json"));
582 return false;
583}
DEFINE_LOG_CATEGORY(LogDlgJsonWriter)
bool UStructToJsonStringInternal(const TSharedRef< FJsonObject > &JsonObject, const int32 InitialIndent, FString &OutJsonString)
UProperty FNYProperty
UNumericProperty FNYNumericProperty
UObjectProperty FNYObjectProperty
FORCEINLINE const uint8 * GetConstRawPtr(int32 Index=0) const
Definition DlgHelper.h:49
FORCEINLINE const uint8 * GetConstValuePtr(int32 Index) const
Definition DlgHelper.h:72
FORCEINLINE const uint8 * GetConstKeyPtr(int32 Index) const
Definition DlgHelper.h:67
bool UStructToJsonString(const UStruct *StructDefinition, const void *const ContainerPtr, const DlgJsonWriterOptions &Options, FString &OutJsonString)
static constexpr int64 CheckFlags
TSharedPtr< FJsonValue > PropertyToJsonValue(const FNYProperty *Property, const void *const ContainerPtr, const void *const ValuePtr)
bool UStructToJsonObject(const UStruct *StructDefinition, const void *const ContainerPtr, TSharedRef< FJsonObject > &OutJsonObject)
void Write(const UStruct *StructDefinition, const void *ContainerPtr) override
TSharedPtr< FJsonValue > ConvertScalarPropertyToJsonValue(const FNYProperty *Property, const void *const ContainerPtr, const void *const ValuePtr)
bool UStructToJsonAttributes(const UStruct *StructDefinition, const void *const ContainerPtr, TMap< FString, TSharedPtr< FJsonValue > > &OutJsonAttributes)
virtual bool CanSaveAsReference(const FNYProperty *Property, const UObject *Object)
Definition IDlgWriter.h:83
static bool CanSkipProperty(const FNYProperty *Property)
Definition IDlgWriter.h:41
bool bLogVerbose
Definition IDlgWriter.h:116
static bool CanWriteIndex(const FNYProperty *Property)
Definition IDlgWriter.h:73