From c7936215671c145b03df74f4eabf8e924cf8617f Mon Sep 17 00:00:00 2001 From: Andrei Burdulescu Date: Mon, 8 Aug 2022 21:30:06 +0300 Subject: [PATCH] [golang] Add support for text parsing with json struct tags (#7353) * [golang] Add support for text parsing with json struct tags Add struct tags to Go native structs generated when object API is used. This allows to use the same JSON file as for C++ text parsing(i.e. snake_case vs CamelCase) and thus enabling text parsing for Go(when using object API). * [golang] Add test for text parsing Added small test to check and demonstrate text parsing in Go. Also, ran clang-format on cpp file changes. --- src/idl_gen_go.cpp | 3 +- tests/MyGame/Example/Ability.go | 4 +- tests/MyGame/Example/Monster.go | 100 +++++++++--------- tests/MyGame/Example/Referrable.go | 2 +- tests/MyGame/Example/Stat.go | 6 +- tests/MyGame/Example/StructOfStructs.go | 6 +- .../Example/StructOfStructsOfStructs.go | 2 +- tests/MyGame/Example/Test.go | 4 +- .../MyGame/Example/TestSimpleTableWithEnum.go | 2 +- tests/MyGame/Example/TypeAliases.go | 24 ++--- tests/MyGame/Example/Vec3.go | 12 +-- tests/go_test.go | 34 +++++- tests/optional_scalars/ScalarStuff.go | 72 ++++++------- 13 files changed, 151 insertions(+), 120 deletions(-) diff --git a/src/idl_gen_go.cpp b/src/idl_gen_go.cpp index 37392036554..abd9b24f9f2 100644 --- a/src/idl_gen_go.cpp +++ b/src/idl_gen_go.cpp @@ -842,7 +842,8 @@ class GoGenerator : public BaseGenerator { continue; code += "\t" + namer_.Field(field) + " "; if (field.IsScalarOptional()) { code += "*"; } - code += NativeType(field.value.type) + "\n"; + code += NativeType(field.value.type) + " `json:\"" + field.name + "\"`" + + "\n"; } code += "}\n\n"; diff --git a/tests/MyGame/Example/Ability.go b/tests/MyGame/Example/Ability.go index 9852a755357..ae869aafd41 100644 --- a/tests/MyGame/Example/Ability.go +++ b/tests/MyGame/Example/Ability.go @@ -7,8 +7,8 @@ import ( ) type AbilityT struct { - Id uint32 - Distance uint32 + Id uint32 `json:"id"` + Distance uint32 `json:"distance"` } func (t *AbilityT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT { diff --git a/tests/MyGame/Example/Monster.go b/tests/MyGame/Example/Monster.go index 067be0dfbfe..237896c9b89 100644 --- a/tests/MyGame/Example/Monster.go +++ b/tests/MyGame/Example/Monster.go @@ -10,56 +10,56 @@ import ( /// an example documentation comment: "monster object" type MonsterT struct { - Pos *Vec3T - Mana int16 - Hp int16 - Name string - Inventory []byte - Color Color - Test *AnyT - Test4 []*TestT - Testarrayofstring []string - Testarrayoftables []*MonsterT - Enemy *MonsterT - Testnestedflatbuffer []byte - Testempty *StatT - Testbool bool - Testhashs32Fnv1 int32 - Testhashu32Fnv1 uint32 - Testhashs64Fnv1 int64 - Testhashu64Fnv1 uint64 - Testhashs32Fnv1a int32 - Testhashu32Fnv1a uint32 - Testhashs64Fnv1a int64 - Testhashu64Fnv1a uint64 - Testarrayofbools []bool - Testf float32 - Testf2 float32 - Testf3 float32 - Testarrayofstring2 []string - Testarrayofsortedstruct []*AbilityT - Flex []byte - Test5 []*TestT - VectorOfLongs []int64 - VectorOfDoubles []float64 - ParentNamespaceTest *MyGame.InParentNamespaceT - VectorOfReferrables []*ReferrableT - SingleWeakReference uint64 - VectorOfWeakReferences []uint64 - VectorOfStrongReferrables []*ReferrableT - CoOwningReference uint64 - VectorOfCoOwningReferences []uint64 - NonOwningReference uint64 - VectorOfNonOwningReferences []uint64 - AnyUnique *AnyUniqueAliasesT - AnyAmbiguous *AnyAmbiguousAliasesT - VectorOfEnums []Color - SignedEnum Race - Testrequirednestedflatbuffer []byte - ScalarKeySortedTables []*StatT - NativeInline *TestT - LongEnumNonEnumDefault LongEnum - LongEnumNormalDefault LongEnum + Pos *Vec3T `json:"pos"` + Mana int16 `json:"mana"` + Hp int16 `json:"hp"` + Name string `json:"name"` + Inventory []byte `json:"inventory"` + Color Color `json:"color"` + Test *AnyT `json:"test"` + Test4 []*TestT `json:"test4"` + Testarrayofstring []string `json:"testarrayofstring"` + Testarrayoftables []*MonsterT `json:"testarrayoftables"` + Enemy *MonsterT `json:"enemy"` + Testnestedflatbuffer []byte `json:"testnestedflatbuffer"` + Testempty *StatT `json:"testempty"` + Testbool bool `json:"testbool"` + Testhashs32Fnv1 int32 `json:"testhashs32_fnv1"` + Testhashu32Fnv1 uint32 `json:"testhashu32_fnv1"` + Testhashs64Fnv1 int64 `json:"testhashs64_fnv1"` + Testhashu64Fnv1 uint64 `json:"testhashu64_fnv1"` + Testhashs32Fnv1a int32 `json:"testhashs32_fnv1a"` + Testhashu32Fnv1a uint32 `json:"testhashu32_fnv1a"` + Testhashs64Fnv1a int64 `json:"testhashs64_fnv1a"` + Testhashu64Fnv1a uint64 `json:"testhashu64_fnv1a"` + Testarrayofbools []bool `json:"testarrayofbools"` + Testf float32 `json:"testf"` + Testf2 float32 `json:"testf2"` + Testf3 float32 `json:"testf3"` + Testarrayofstring2 []string `json:"testarrayofstring2"` + Testarrayofsortedstruct []*AbilityT `json:"testarrayofsortedstruct"` + Flex []byte `json:"flex"` + Test5 []*TestT `json:"test5"` + VectorOfLongs []int64 `json:"vector_of_longs"` + VectorOfDoubles []float64 `json:"vector_of_doubles"` + ParentNamespaceTest *MyGame.InParentNamespaceT `json:"parent_namespace_test"` + VectorOfReferrables []*ReferrableT `json:"vector_of_referrables"` + SingleWeakReference uint64 `json:"single_weak_reference"` + VectorOfWeakReferences []uint64 `json:"vector_of_weak_references"` + VectorOfStrongReferrables []*ReferrableT `json:"vector_of_strong_referrables"` + CoOwningReference uint64 `json:"co_owning_reference"` + VectorOfCoOwningReferences []uint64 `json:"vector_of_co_owning_references"` + NonOwningReference uint64 `json:"non_owning_reference"` + VectorOfNonOwningReferences []uint64 `json:"vector_of_non_owning_references"` + AnyUnique *AnyUniqueAliasesT `json:"any_unique"` + AnyAmbiguous *AnyAmbiguousAliasesT `json:"any_ambiguous"` + VectorOfEnums []Color `json:"vector_of_enums"` + SignedEnum Race `json:"signed_enum"` + Testrequirednestedflatbuffer []byte `json:"testrequirednestedflatbuffer"` + ScalarKeySortedTables []*StatT `json:"scalar_key_sorted_tables"` + NativeInline *TestT `json:"native_inline"` + LongEnumNonEnumDefault LongEnum `json:"long_enum_non_enum_default"` + LongEnumNormalDefault LongEnum `json:"long_enum_normal_default"` } func (t *MonsterT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT { diff --git a/tests/MyGame/Example/Referrable.go b/tests/MyGame/Example/Referrable.go index 66c59729c3a..aa270798425 100644 --- a/tests/MyGame/Example/Referrable.go +++ b/tests/MyGame/Example/Referrable.go @@ -7,7 +7,7 @@ import ( ) type ReferrableT struct { - Id uint64 + Id uint64 `json:"id"` } func (t *ReferrableT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT { diff --git a/tests/MyGame/Example/Stat.go b/tests/MyGame/Example/Stat.go index 5c060d1afa2..71496409843 100644 --- a/tests/MyGame/Example/Stat.go +++ b/tests/MyGame/Example/Stat.go @@ -7,9 +7,9 @@ import ( ) type StatT struct { - Id string - Val int64 - Count uint16 + Id string `json:"id"` + Val int64 `json:"val"` + Count uint16 `json:"count"` } func (t *StatT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT { diff --git a/tests/MyGame/Example/StructOfStructs.go b/tests/MyGame/Example/StructOfStructs.go index 35ccfcb41c0..22281b6699f 100644 --- a/tests/MyGame/Example/StructOfStructs.go +++ b/tests/MyGame/Example/StructOfStructs.go @@ -7,9 +7,9 @@ import ( ) type StructOfStructsT struct { - A *AbilityT - B *TestT - C *AbilityT + A *AbilityT `json:"a"` + B *TestT `json:"b"` + C *AbilityT `json:"c"` } func (t *StructOfStructsT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT { diff --git a/tests/MyGame/Example/StructOfStructsOfStructs.go b/tests/MyGame/Example/StructOfStructsOfStructs.go index 61dd62f2e04..b8f32a0dc97 100644 --- a/tests/MyGame/Example/StructOfStructsOfStructs.go +++ b/tests/MyGame/Example/StructOfStructsOfStructs.go @@ -7,7 +7,7 @@ import ( ) type StructOfStructsOfStructsT struct { - A *StructOfStructsT + A *StructOfStructsT `json:"a"` } func (t *StructOfStructsOfStructsT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT { diff --git a/tests/MyGame/Example/Test.go b/tests/MyGame/Example/Test.go index cbf7e29a13b..149171171f4 100644 --- a/tests/MyGame/Example/Test.go +++ b/tests/MyGame/Example/Test.go @@ -7,8 +7,8 @@ import ( ) type TestT struct { - A int16 - B int8 + A int16 `json:"a"` + B int8 `json:"b"` } func (t *TestT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT { diff --git a/tests/MyGame/Example/TestSimpleTableWithEnum.go b/tests/MyGame/Example/TestSimpleTableWithEnum.go index b8cde12b861..553867fe436 100644 --- a/tests/MyGame/Example/TestSimpleTableWithEnum.go +++ b/tests/MyGame/Example/TestSimpleTableWithEnum.go @@ -7,7 +7,7 @@ import ( ) type TestSimpleTableWithEnumT struct { - Color Color + Color Color `json:"color"` } func (t *TestSimpleTableWithEnumT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT { diff --git a/tests/MyGame/Example/TypeAliases.go b/tests/MyGame/Example/TypeAliases.go index d018fa1f619..9ded35e6f56 100644 --- a/tests/MyGame/Example/TypeAliases.go +++ b/tests/MyGame/Example/TypeAliases.go @@ -7,18 +7,18 @@ import ( ) type TypeAliasesT struct { - I8 int8 - U8 byte - I16 int16 - U16 uint16 - I32 int32 - U32 uint32 - I64 int64 - U64 uint64 - F32 float32 - F64 float64 - V8 []int8 - Vf64 []float64 + I8 int8 `json:"i8"` + U8 byte `json:"u8"` + I16 int16 `json:"i16"` + U16 uint16 `json:"u16"` + I32 int32 `json:"i32"` + U32 uint32 `json:"u32"` + I64 int64 `json:"i64"` + U64 uint64 `json:"u64"` + F32 float32 `json:"f32"` + F64 float64 `json:"f64"` + V8 []int8 `json:"v8"` + Vf64 []float64 `json:"vf64"` } func (t *TypeAliasesT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT { diff --git a/tests/MyGame/Example/Vec3.go b/tests/MyGame/Example/Vec3.go index 08311ed025f..16a05cde8c6 100644 --- a/tests/MyGame/Example/Vec3.go +++ b/tests/MyGame/Example/Vec3.go @@ -7,12 +7,12 @@ import ( ) type Vec3T struct { - X float32 - Y float32 - Z float32 - Test1 float64 - Test2 Color - Test3 *TestT + X float32 `json:"x"` + Y float32 `json:"y"` + Z float32 `json:"z"` + Test1 float64 `json:"test1"` + Test2 Color `json:"test2"` + Test3 *TestT `json:"test3"` } func (t *Vec3T) Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT { diff --git a/tests/go_test.go b/tests/go_test.go index 6e1661104db..8cb7b97f36b 100644 --- a/tests/go_test.go +++ b/tests/go_test.go @@ -17,8 +17,9 @@ package main import ( - mygame "MyGame" // refers to generated code - example "MyGame/Example" // refers to generated code + mygame "MyGame" // refers to generated code + example "MyGame/Example" // refers to generated code + "encoding/json" optional_scalars "optional_scalars" // refers to generated code "bytes" @@ -68,6 +69,35 @@ func TestMain(m *testing.M) { os.Exit(m.Run()) } +// TestTextParsing test if text parsing works with object API. +func TestTextParsing(t *testing.T) { + expectedMonster := example.MonsterT{ + Mana: 42, + Name: "foo", + LongEnumNormalDefault: example.LongEnumLongTwo, + } + + buf := new(bytes.Buffer) + if err := json.NewEncoder(buf).Encode(expectedMonster); err != nil { + t.Fatal(err) + } + + var monster example.MonsterT + if err := json.NewDecoder(buf).Decode(&monster); err != nil { + t.Fatal(err) + } + + if monster.Mana != expectedMonster.Mana { + t.Fatal("wrong mana:", monster.Mana) + } + if monster.Name != expectedMonster.Name { + t.Fatal("wrong name:", monster.Name) + } + if monster.LongEnumNormalDefault != expectedMonster.LongEnumNormalDefault { + t.Fatal("wrong enum:", monster.LongEnumNormalDefault) + } +} + // TestAll runs all checks, failing if any errors occur. func TestAll(t *testing.T) { // Verify that the Go FlatBuffers runtime library generates the diff --git a/tests/optional_scalars/ScalarStuff.go b/tests/optional_scalars/ScalarStuff.go index 2992f300284..8b56567cab8 100644 --- a/tests/optional_scalars/ScalarStuff.go +++ b/tests/optional_scalars/ScalarStuff.go @@ -7,42 +7,42 @@ import ( ) type ScalarStuffT struct { - JustI8 int8 - MaybeI8 *int8 - DefaultI8 int8 - JustU8 byte - MaybeU8 *byte - DefaultU8 byte - JustI16 int16 - MaybeI16 *int16 - DefaultI16 int16 - JustU16 uint16 - MaybeU16 *uint16 - DefaultU16 uint16 - JustI32 int32 - MaybeI32 *int32 - DefaultI32 int32 - JustU32 uint32 - MaybeU32 *uint32 - DefaultU32 uint32 - JustI64 int64 - MaybeI64 *int64 - DefaultI64 int64 - JustU64 uint64 - MaybeU64 *uint64 - DefaultU64 uint64 - JustF32 float32 - MaybeF32 *float32 - DefaultF32 float32 - JustF64 float64 - MaybeF64 *float64 - DefaultF64 float64 - JustBool bool - MaybeBool *bool - DefaultBool bool - JustEnum OptionalByte - MaybeEnum *OptionalByte - DefaultEnum OptionalByte + JustI8 int8 `json:"just_i8"` + MaybeI8 *int8 `json:"maybe_i8"` + DefaultI8 int8 `json:"default_i8"` + JustU8 byte `json:"just_u8"` + MaybeU8 *byte `json:"maybe_u8"` + DefaultU8 byte `json:"default_u8"` + JustI16 int16 `json:"just_i16"` + MaybeI16 *int16 `json:"maybe_i16"` + DefaultI16 int16 `json:"default_i16"` + JustU16 uint16 `json:"just_u16"` + MaybeU16 *uint16 `json:"maybe_u16"` + DefaultU16 uint16 `json:"default_u16"` + JustI32 int32 `json:"just_i32"` + MaybeI32 *int32 `json:"maybe_i32"` + DefaultI32 int32 `json:"default_i32"` + JustU32 uint32 `json:"just_u32"` + MaybeU32 *uint32 `json:"maybe_u32"` + DefaultU32 uint32 `json:"default_u32"` + JustI64 int64 `json:"just_i64"` + MaybeI64 *int64 `json:"maybe_i64"` + DefaultI64 int64 `json:"default_i64"` + JustU64 uint64 `json:"just_u64"` + MaybeU64 *uint64 `json:"maybe_u64"` + DefaultU64 uint64 `json:"default_u64"` + JustF32 float32 `json:"just_f32"` + MaybeF32 *float32 `json:"maybe_f32"` + DefaultF32 float32 `json:"default_f32"` + JustF64 float64 `json:"just_f64"` + MaybeF64 *float64 `json:"maybe_f64"` + DefaultF64 float64 `json:"default_f64"` + JustBool bool `json:"just_bool"` + MaybeBool *bool `json:"maybe_bool"` + DefaultBool bool `json:"default_bool"` + JustEnum OptionalByte `json:"just_enum"` + MaybeEnum *OptionalByte `json:"maybe_enum"` + DefaultEnum OptionalByte `json:"default_enum"` } func (t *ScalarStuffT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT {