[C#] support Json Serialization (#5752)
authormugisoba <51015092+mugisoba@users.noreply.github.com>
Tue, 11 Feb 2020 01:43:36 +0000 (10:43 +0900)
committerGitHub <noreply@github.com>
Tue, 11 Feb 2020 01:43:36 +0000 (17:43 -0800)
* support json serialization

* fix invalid json format.
* string must be written with double quotes.
* remove commma after the last object member.

* fix indent

* Revert "fix invalid json format."

This reverts commit d6820ed50c8e3d3cda3aa1849b3079f853608619.

* quated string value.

* add cs-gen-json-serializer flag.

* fix preprocessor indent

* ENABLE_JSON_SERIALIZATION -> ENABLE_JSON_SERIALIZATION_TEST

* share TestBuffer method

* remove ENABLE_JSON_SERIALIZATION

* remove duplicated test data

* [windows] add nuget restore and copy test data.

* [docker mono] share msbuild settings with windows. add nuget restore and copy test data.

* add some note for json api.

43 files changed:
appveyor.yml
docs/source/CsharpUsage.md
include/flatbuffers/idl.h
src/flatc.cpp
src/idl_gen_csharp.cpp
tests/FlatBuffers.Test/FlatBuffers.Test.csproj
tests/FlatBuffers.Test/FlatBuffersExampleTests.cs
tests/FlatBuffers.Test/NetTest.sh
tests/FlatBuffers.Test/Resources/.gitkeep [new file with mode: 0644]
tests/FlatBuffers.Test/Resources/monsterdata_test.mon [deleted file]
tests/FlatBuffers.Test/packages.config [new file with mode: 0644]
tests/MyGame/Example/Ability.cs
tests/MyGame/Example/Any.cs
tests/MyGame/Example/AnyAmbiguousAliases.cs
tests/MyGame/Example/AnyUniqueAliases.cs
tests/MyGame/Example/ArrayStruct.cs
tests/MyGame/Example/ArrayTable.cs
tests/MyGame/Example/Color.cs
tests/MyGame/Example/Monster.cs
tests/MyGame/Example/NestedStruct.cs
tests/MyGame/Example/Race.cs
tests/MyGame/Example/Referrable.cs
tests/MyGame/Example/Stat.cs
tests/MyGame/Example/Test.cs
tests/MyGame/Example/TestEnum.cs
tests/MyGame/Example/TestSimpleTableWithEnum.cs
tests/MyGame/Example/TypeAliases.cs
tests/MyGame/Example/Vec3.cs
tests/MyGame/MonsterExtra.cs
tests/generate_code.bat
tests/generate_code.sh
tests/monsterdata_test.json
tests/namespace_test/NamespaceA/NamespaceB/EnumInNestedNS.cs
tests/namespace_test/NamespaceA/NamespaceB/StructInNestedNS.cs
tests/namespace_test/NamespaceA/NamespaceB/TableInNestedNS.cs
tests/namespace_test/NamespaceA/SecondTableInA.cs
tests/namespace_test/NamespaceA/TableInFirstNS.cs
tests/namespace_test/NamespaceC/TableInC.cs
tests/union_vector/Attacker.cs
tests/union_vector/BookReader.cs
tests/union_vector/Character.cs
tests/union_vector/Movie.cs
tests/union_vector/Rapunzel.cs

index ee6930f..e42fece 100644 (file)
@@ -105,6 +105,11 @@ test_script:
   # Have to compile this here rather than in "build" above because AppVeyor only
   # supports building one project??
   - "cd FlatBuffers.Test"
+  - "copy ..\\monsterdata_test.mon Resources\\"
+  - "copy ..\\monsterdata_test.json Resources\\"
+  - "dotnet new sln"
+  - "dotnet sln add FlatBuffers.Test.csproj"
+  - "nuget restore"
   - "msbuild.exe /property:Configuration=Release;OutputPath=tempcs /verbosity:minimal FlatBuffers.Test.csproj"
   - "tempcs\\FlatBuffers.Test.exe"
   # Run tests with UNSAFE_BYTEBUFFER
index 90a757f..f7f585d 100644 (file)
@@ -151,4 +151,25 @@ To use:
     fbb.Finish(Monster.Pack(fbb, monsterobj).Value);
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
+### Json Serialization
+
+An additional feature of the object API is the ability to allow you to
+serialize & deserialize a JSON text. 
+To use Json Serialization, add `--gen-json-serializer` option to `flatc` and
+add `Newtonsoft.Json` nuget package to csproj.
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cs}
+    // Deserialize MonsterT from json
+    string jsonText = File.ReadAllText(@"Resources/monsterdata_test.json");
+    MonsterT mon = MonsterT.DeserializeFromJson(jsonText);
+
+    // Serialize MonsterT to json
+    string jsonText2 = mon.SerializeToJson();
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+* Limitation
+  * `hash` attribute currentry not supported.
+* NuGet package Dependency
+  * [Newtonsoft.Json](https://github.com/JamesNK/Newtonsoft.Json)
+
 <br>
index 2e2d468..dbdacc8 100644 (file)
@@ -556,6 +556,7 @@ struct IDLOptions {
   std::string root_type;
   bool force_defaults;
   bool java_primitive_has_method;
+  bool cs_gen_json_serializer;
   std::vector<std::string> cpp_includes;
   std::string cpp_std;
   std::string proto_namespace_suffix;
@@ -592,12 +593,12 @@ struct IDLOptions {
   // for code generation.
   unsigned long lang_to_generate;
 
-  // If set (default behavior), empty string fields will be set to nullptr to make
-  // the flatbuffer more compact.
+  // If set (default behavior), empty string fields will be set to nullptr to
+  // make the flatbuffer more compact.
   bool set_empty_strings_to_null;
 
-  // If set (default behavior), empty vector fields will be set to nullptr to make
-  // the flatbuffer more compact.
+  // If set (default behavior), empty vector fields will be set to nullptr to
+  // make the flatbuffer more compact.
   bool set_empty_vectors_to_null;
 
   IDLOptions()
@@ -641,6 +642,7 @@ struct IDLOptions {
         size_prefixed(false),
         force_defaults(false),
         java_primitive_has_method(false),
+        cs_gen_json_serializer(false),
         lang(IDLOptions::kJava),
         mini_reflect(IDLOptions::kNone),
         lang_to_generate(0),
@@ -1119,9 +1121,8 @@ bool GenerateJavaGRPC(const Parser &parser, const std::string &path,
 
 // Generate GRPC Python interfaces.
 // See idl_gen_grpc.cpp.
-bool GeneratePythonGRPC(const Parser &parser,
-                    const std::string &path,
-                    const std::string &file_name);
+bool GeneratePythonGRPC(const Parser &parser, const std::string &path,
+                        const std::string &file_name);
 
 }  // namespace flatbuffers
 
index bac3411..1be8175 100644 (file)
@@ -325,7 +325,7 @@ int FlatCompiler::Compile(int argc, const char **argv) {
       } else if (arg == "--bfbs-builtins") {
         opts.binary_schema_builtins = true;
       } else if (arg == "--bfbs-gen-embed") {
-        opts.binary_schema_gen_embed= true;
+        opts.binary_schema_gen_embed = true;
       } else if (arg == "--no-fb-import") {
         opts.skip_flatbuffers_import = true;
       } else if (arg == "--no-ts-reexport") {
@@ -348,10 +348,13 @@ int FlatCompiler::Compile(int argc, const char **argv) {
         opts.set_empty_vectors_to_null = false;
       } else if (arg == "--java-primitive-has-method") {
         opts.java_primitive_has_method = true;
+      } else if (arg == "--cs-gen-json-serializer") {
+        opts.cs_gen_json_serializer = true;
       } else if (arg == "--flexbuffers") {
         opts.use_flexbuffers = true;
-      } else if(arg == "--cpp-std") {
-        if (++argi >= argc) Error("missing C++ standard specification" + arg, true);
+      } else if (arg == "--cpp-std") {
+        if (++argi >= argc)
+          Error("missing C++ standard specification" + arg, true);
         opts.cpp_std = argv[argi];
       } else {
         for (size_t i = 0; i < params_.num_generators; ++i) {
index a97ae6b..4bcde6c 100644 (file)
@@ -271,6 +271,11 @@ class CSharpGenerator : public BaseGenerator {
     // That, and Java Enums are expensive, and not universally liked.
     GenComment(enum_def.doc_comment, code_ptr, &comment_config);
 
+    if (opts.cs_gen_json_serializer && opts.generate_object_based_api) {
+      code +=
+          "[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters."
+          "StringEnumConverter))]\n";
+    }
     // In C# this indicates enumeration values can be treated as bit flags.
     if (enum_def.attributes.Lookup("bit_flags")) {
       code += "[System.FlagsAttribute]\n";
@@ -1274,6 +1279,89 @@ class CSharpGenerator : public BaseGenerator {
     code += "    }\n";
     code += "  }\n";
     code += "}\n\n";
+    // JsonConverter
+    if (opts.cs_gen_json_serializer) {
+      if (enum_def.attributes.Lookup("private")) {
+        code += "internal ";
+      } else {
+        code += "public ";
+      }
+      code += "class " + union_name +
+              "_JsonConverter : Newtonsoft.Json.JsonConverter {\n";
+      code += "  public override bool CanConvert(System.Type objectType) {\n";
+      code += "    return objectType == typeof(" + union_name +
+              ") || objectType == typeof(System.Collections.Generic.List<" +
+              union_name + ">);\n";
+      code += "  }\n";
+      code +=
+          "  public override void WriteJson(Newtonsoft.Json.JsonWriter writer, "
+          "object value, "
+          "Newtonsoft.Json.JsonSerializer serializer) {\n";
+      code += "    var _olist = value as System.Collections.Generic.List<" +
+              union_name + ">;\n";
+      code += "    if (_olist != null) {\n";
+      code += "      writer.WriteStartArray();\n";
+      code +=
+          "      foreach (var _o in _olist) { this.WriteJson(writer, _o, "
+          "serializer); }\n";
+      code += "      writer.WriteEndArray();\n";
+      code += "    } else {\n";
+      code += "      this.WriteJson(writer, value as " + union_name +
+              ", serializer);\n";
+      code += "    }\n";
+      code += "  }\n";
+      code += "  public void WriteJson(Newtonsoft.Json.JsonWriter writer, " +
+              union_name +
+              " _o, "
+              "Newtonsoft.Json.JsonSerializer serializer) {\n";
+      code += "    if (_o == null) return;\n";
+      code += "    serializer.Serialize(writer, _o.Value);\n";
+      code += "  }\n";
+      code +=
+          "  public override object ReadJson(Newtonsoft.Json.JsonReader "
+          "reader, "
+          "System.Type objectType, "
+          "object existingValue, Newtonsoft.Json.JsonSerializer serializer) "
+          "{\n";
+      code +=
+          "    var _olist = existingValue as System.Collections.Generic.List<" +
+          union_name + ">;\n";
+      code += "    if (_olist != null) {\n";
+      code += "      for (var _j = 0; _j < _olist.Count; ++_j) {\n";
+      code += "        reader.Read();\n";
+      code +=
+          "        _olist[_j] = this.ReadJson(reader, _olist[_j], "
+          "serializer);\n";
+      code += "      }\n";
+      code += "      reader.Read();\n";
+      code += "      return _olist;\n";
+      code += "    } else {\n";
+      code += "      return this.ReadJson(reader, existingValue as " +
+              union_name + ", serializer);\n";
+      code += "    }\n";
+      code += "  }\n";
+      code += "  public " + union_name +
+              " ReadJson(Newtonsoft.Json.JsonReader reader, " + union_name +
+              " _o, Newtonsoft.Json.JsonSerializer serializer) {\n";
+      code += "    if (_o == null) return null;\n";
+      code += "    switch (_o.Type) {\n";
+      for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end();
+           ++it) {
+        auto &ev = **it;
+        if (ev.union_type.base_type == BASE_TYPE_NONE) {
+          code += "      default: break;\n";
+        } else {
+          auto type_name = GenTypeGet_ObjectAPI(ev.union_type, opts);
+          code += "      case " + enum_def.name + "." + ev.name +
+                  ": _o.Value = serializer.Deserialize<" + type_name +
+                  ">(reader); break;\n";
+        }
+      }
+      code += "    }\n";
+      code += "    return _o;\n";
+      code += "  }\n";
+      code += "}\n\n";
+    }
   }
 
   std::string GenTypeName_ObjectAPI(const std::string &name,
@@ -1794,8 +1882,62 @@ class CSharpGenerator : public BaseGenerator {
       if (field.value.type.base_type == BASE_TYPE_UTYPE) continue;
       if (field.value.type.element == BASE_TYPE_UTYPE) continue;
       auto type_name = GenTypeGet_ObjectAPI(field.value.type, opts);
-      code += "  public " + type_name + " " + MakeCamel(field.name, true) +
-              " { get; set; }\n";
+      auto camel_name = MakeCamel(field.name, true);
+      if (opts.cs_gen_json_serializer) {
+        if (IsUnion(field.value.type)) {
+          auto utype_name = WrapInNameSpace(*field.value.type.enum_def);
+          code +=
+              "  [Newtonsoft.Json.JsonProperty(\"" + field.name + "_type\")]\n";
+          if (field.value.type.base_type == BASE_TYPE_VECTOR) {
+            code += "  private " + utype_name + "[] " + camel_name + "Type {\n";
+            code += "    get {\n";
+            code += "      if (this." + camel_name + " == null) return null;\n";
+            code += "      var _o = new " + utype_name + "[this." + camel_name +
+                    ".Count];\n";
+            code +=
+                "      for (var _j = 0; _j < _o.Length; ++_j) { _o[_j] = "
+                "this." +
+                camel_name + "[_j].Type; }\n";
+            code += "      return _o;\n";
+            code += "    }\n";
+            code += "    set {\n";
+            code += "      this." + camel_name + " = new List<" + utype_name +
+                    "Union>();\n";
+            code += "      for (var _j = 0; _j < value.Length; ++_j) {\n";
+            code += "        var _o = new " + utype_name + "Union();\n";
+            code += "        _o.Type = value[_j];\n";
+            code += "        this." + camel_name + ".Add(_o);\n";
+            code += "      }\n";
+            code += "    }\n";
+            code += "  }\n";
+          } else {
+            code += "  private " + utype_name + " " + camel_name + "Type {\n";
+            code += "    get {\n";
+            code += "      return this." + camel_name + " != null ? this." +
+                    camel_name + ".Type : " + utype_name + ".NONE;\n";
+            code += "    }\n";
+            code += "    set {\n";
+            code += "      this." + camel_name + " = new " + utype_name +
+                    "Union();\n";
+            code += "      this." + camel_name + ".Type = value;\n";
+            code += "    }\n";
+            code += "  }\n";
+          }
+        }
+        code += "  [Newtonsoft.Json.JsonProperty(\"" + field.name + "\")]\n";
+        if (IsUnion(field.value.type)) {
+          auto union_name =
+              (field.value.type.base_type == BASE_TYPE_VECTOR)
+                  ? GenTypeGet_ObjectAPI(field.value.type.VectorType(), opts)
+                  : type_name;
+          code += "  [Newtonsoft.Json.JsonConverter(typeof(" + union_name +
+                  "_JsonConverter))]\n";
+        }
+        if (field.attributes.Lookup("hash")) {
+          code += "  [Newtonsoft.Json.JsonIgnore()]\n";
+        }
+      }
+      code += "  public " + type_name + " " + camel_name + " { get; set; }\n";
     }
     // Generate Constructor
     code += "\n";
@@ -1833,6 +1975,21 @@ class CSharpGenerator : public BaseGenerator {
       }
     }
     code += "  }\n";
+    // Generate Serialization
+    if (opts.cs_gen_json_serializer &&
+        parser_.root_struct_def_ == &struct_def) {
+      code += "\n";
+      code += "  public static " + class_name +
+              " DeserializeFromJson(string jsonText) {\n";
+      code += "    return Newtonsoft.Json.JsonConvert.DeserializeObject<" +
+              class_name + ">(jsonText);\n";
+      code += "  }\n";
+      code += "  public string SerializeToJson() {\n";
+      code +=
+          "    return Newtonsoft.Json.JsonConvert.SerializeObject(this, "
+          "Newtonsoft.Json.Formatting.Indented);\n";
+      code += "  }\n";
+    }
     code += "}\n\n";
   }
 
index 3f064b4..c917d2f 100644 (file)
@@ -17,7 +17,7 @@
     <DebugType>full</DebugType>
     <Optimize>false</Optimize>
     <OutputPath>bin\Debug\</OutputPath>
-    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DefineConstants>TRACE;DEBUG</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
   </PropertyGroup>
@@ -37,6 +37,9 @@
     <DefineConstants>$(DefineConstants);UNSAFE_BYTEBUFFER</DefineConstants>
   </PropertyGroup>
   <ItemGroup>
+    <Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
+      <HintPath>packages\Newtonsoft.Json.12.0.3\lib\net35\Newtonsoft.Json.dll</HintPath>
+    </Reference>
     <Reference Include="System" />
     <Reference Include="System.Core">
       <RequiredTargetFramework>3.5</RequiredTargetFramework>
       <Link>Resources\monsterdata_test.mon</Link>
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
     </Content>
+    <Content Include="..\monsterdata_test.json">
+      <Link>Resources\monsterdata_test.json</Link>
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
   </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
index abe0857..7bdc502 100644 (file)
@@ -111,18 +111,18 @@ namespace FlatBuffers.Test
             }
 
             // Dump to output directory so we can inspect later, if needed
-#if ENABLE_SPAN_T
+            #if ENABLE_SPAN_T
             var data = fbb.DataBuffer.ToSizedArray();
             string filename = @"Resources/monsterdata_cstest" + (sizePrefix ? "_sp" : "") + ".mon";
             File.WriteAllBytes(filename, data);
-#else
+            #else
             using (var ms = fbb.DataBuffer.ToMemoryStream(fbb.DataBuffer.Position, fbb.Offset))
             {
                 var data = ms.ToArray();
                 string filename = @"Resources/monsterdata_cstest" + (sizePrefix ? "_sp" : "") + ".mon";
                 File.WriteAllBytes(filename, data);
             }
-#endif
+            #endif
 
             // Remove the size prefix if necessary for further testing
             ByteBuffer dataBuffer = fbb.DataBuffer;
@@ -245,7 +245,7 @@ namespace FlatBuffers.Test
 
             Assert.AreEqual(true, monster.Testbool);
 
-#if ENABLE_SPAN_T
+            #if ENABLE_SPAN_T
             var nameBytes = monster.GetNameBytes();
             Assert.AreEqual("MyMonster", Encoding.UTF8.GetString(nameBytes.ToArray(), 0, nameBytes.Length));
 
@@ -263,7 +263,7 @@ namespace FlatBuffers.Test
 
             var doubleArrayBytes = monster.GetVectorOfDoublesBytes();
             Assert.IsTrue(monster.VectorOfDoublesLength * 8 == doubleArrayBytes.Length);
-#else
+            #else
             var nameBytes = monster.GetNameBytes().Value;
             Assert.AreEqual("MyMonster", Encoding.UTF8.GetString(nameBytes.Array, nameBytes.Offset, nameBytes.Count));
 
@@ -275,7 +275,7 @@ namespace FlatBuffers.Test
             {
                 Assert.IsTrue(monster.GetTestarrayofboolsBytes().HasValue);
             }
-#endif
+            #endif
         }
 
         [FlatBuffersTestMethod]
@@ -288,6 +288,16 @@ namespace FlatBuffers.Test
         }
 
         [FlatBuffersTestMethod]
+        public void CanReadJsonFile()
+        {
+            var jsonText = File.ReadAllText(@"Resources/monsterdata_test.json");
+            var mon = MonsterT.DeserializeFromJson(jsonText);
+            var fbb = new FlatBufferBuilder(1);
+            fbb.Finish(Monster.Pack(fbb, mon).Value);
+            TestBuffer(fbb.DataBuffer);
+        }
+
+        [FlatBuffersTestMethod]
         public void TestEnums()
         {
             Assert.AreEqual("Red", Color.Red.ToString());
@@ -659,6 +669,10 @@ namespace FlatBuffers.Test
             fbb.Finish(Monster.Pack(fbb, b).Value);
             var c = Monster.GetRootAsMonster(fbb.DataBuffer);
             AreEqual(a, c);
+
+            var jsonText = b.SerializeToJson();
+            var d = MonsterT.DeserializeFromJson(jsonText);
+            AreEqual(a, d);
         }
 
         private void AreEqual(ArrayTable a, ArrayTableT b)
@@ -754,6 +768,10 @@ namespace FlatBuffers.Test
             fbb.Finish(ArrayTable.Pack(fbb, b).Value);
             var c = ArrayTable.GetRootAsArrayTable(fbb.DataBuffer);
             AreEqual(a, c);
+
+            var jsonText = b.SerializeToJson();
+            var d = ArrayTableT.DeserializeFromJson(jsonText);
+            AreEqual(a, d);
         }
 
         private void AreEqual(Movie a, MovieT b)
@@ -793,6 +811,10 @@ namespace FlatBuffers.Test
             fbb.Finish(Movie.Pack(fbb, b).Value);
             var c = Movie.GetRootAsMovie(fbb.DataBuffer);
             AreEqual(a, c);
+
+            var jsonText = b.SerializeToJson();
+            var d = MovieT.DeserializeFromJson(jsonText);
+            AreEqual(a, d);
         }
     }
 }
index f03d97f..10d5cdd 100644 (file)
@@ -1,23 +1,41 @@
 #!/bin/sh
 
+# Restore nuget packages
+mkdir dotnet_tmp
+curl -OL https://dot.net/v1/dotnet-install.sh
+chmod +x dotnet-install.sh
+./dotnet-install.sh --version 3.1.101 --install-dir dotnet_tmp
+dotnet_tmp/dotnet new sln
+dotnet_tmp/dotnet sln add FlatBuffers.Test.csproj
+curl -OL https://dist.nuget.org/win-x86-commandline/v5.4.0/nuget.exe
+mono nuget.exe restore
+
+# Copy Test Files
+cp ../monsterdata_test.mon Resources/
+cp ../monsterdata_test.json Resources/
+
 # Testing C# on Linux using Mono.
 
-mcs -debug -out:./fbnettest.exe \
-  ../../net/FlatBuffers/*.cs ../MyGame/Example/*.cs ../MyGame/Example2/*.cs ../MyGame/*.cs ../union_vector/*.cs \
-  FlatBuffersTestClassAttribute.cs FlatBuffersTestMethodAttribute.cs Assert.cs FlatBuffersExampleTests.cs Program.cs ByteBufferTests.cs FlatBufferBuilderTests.cs FlatBuffersFuzzTests.cs FuzzTestData.cs Lcg.cs TestTable.cs
-mono --debug ./fbnettest.exe
-rm fbnettest.exe
+msbuild -property:Configuration=Release,OutputPath=tempcs -verbosity:minimal FlatBuffers.Test.csproj
+mono tempcs/FlatBuffers.Test.exe
+rm -fr tempcs 
 rm Resources/monsterdata_cstest.mon
 rm Resources/monsterdata_cstest_sp.mon
 
 # Repeat with unsafe versions
 
-mcs -debug -out:./fbnettest.exe \
-  -unsafe -d:UNSAFE_BYTEBUFFER \
-  ../../net/FlatBuffers/*.cs ../MyGame/Example/*.cs ../MyGame/Example2/*.cs ../MyGame/*.cs ../union_vector/*.cs\
-  FlatBuffersTestClassAttribute.cs FlatBuffersTestMethodAttribute.cs Assert.cs FlatBuffersExampleTests.cs Program.cs ByteBufferTests.cs FlatBufferBuilderTests.cs FlatBuffersFuzzTests.cs FuzzTestData.cs Lcg.cs TestTable.cs
-mono --debug ./fbnettest.exe
-rm fbnettest.exe
+msbuild -property:Configuration=Release,UnsafeByteBuffer=true,OutputPath=tempcsUnsafe -verbosity:minimal FlatBuffers.Test.csproj
+mono tempcsUnsafe/FlatBuffers.Test.exe
+rm -fr tempcsUnsafe 
 rm Resources/monsterdata_cstest.mon
 rm Resources/monsterdata_cstest_sp.mon
 
+# Remove Temp Files
+rm -fr dotnet_tmp
+rm -fr packages
+rm dotnet-install.sh
+rm nuget.exe
+rm FlatBuffers.Test.sln
+rm Resources/monsterdata_test.mon
+rm Resources/monsterdata_test.json
+
diff --git a/tests/FlatBuffers.Test/Resources/.gitkeep b/tests/FlatBuffers.Test/Resources/.gitkeep
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/FlatBuffers.Test/Resources/monsterdata_test.mon b/tests/FlatBuffers.Test/Resources/monsterdata_test.mon
deleted file mode 100644 (file)
index 3f83972..0000000
Binary files a/tests/FlatBuffers.Test/Resources/monsterdata_test.mon and /dev/null differ
diff --git a/tests/FlatBuffers.Test/packages.config b/tests/FlatBuffers.Test/packages.config
new file mode 100644 (file)
index 0000000..d766d04
--- /dev/null
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="Newtonsoft.Json" version="12.0.3" targetFramework="net35" />
+</packages>
\ No newline at end of file
index 1db6a02..bd49ccd 100644 (file)
@@ -47,7 +47,9 @@ public struct Ability : IFlatbufferObject
 
 public class AbilityT
 {
+  [Newtonsoft.Json.JsonProperty("id")]
   public uint Id { get; set; }
+  [Newtonsoft.Json.JsonProperty("distance")]
   public uint Distance { get; set; }
 
   public AbilityT() {
index a331209..edf98ef 100644 (file)
@@ -5,6 +5,7 @@
 namespace MyGame.Example
 {
 
+[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))]
 public enum Any : byte
 {
   NONE = 0,
@@ -37,5 +38,48 @@ public class AnyUnion {
   }
 }
 
+public class AnyUnion_JsonConverter : Newtonsoft.Json.JsonConverter {
+  public override bool CanConvert(System.Type objectType) {
+    return objectType == typeof(AnyUnion) || objectType == typeof(System.Collections.Generic.List<AnyUnion>);
+  }
+  public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) {
+    var _olist = value as System.Collections.Generic.List<AnyUnion>;
+    if (_olist != null) {
+      writer.WriteStartArray();
+      foreach (var _o in _olist) { this.WriteJson(writer, _o, serializer); }
+      writer.WriteEndArray();
+    } else {
+      this.WriteJson(writer, value as AnyUnion, serializer);
+    }
+  }
+  public void WriteJson(Newtonsoft.Json.JsonWriter writer, AnyUnion _o, Newtonsoft.Json.JsonSerializer serializer) {
+    if (_o == null) return;
+    serializer.Serialize(writer, _o.Value);
+  }
+  public override object ReadJson(Newtonsoft.Json.JsonReader reader, System.Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) {
+    var _olist = existingValue as System.Collections.Generic.List<AnyUnion>;
+    if (_olist != null) {
+      for (var _j = 0; _j < _olist.Count; ++_j) {
+        reader.Read();
+        _olist[_j] = this.ReadJson(reader, _olist[_j], serializer);
+      }
+      reader.Read();
+      return _olist;
+    } else {
+      return this.ReadJson(reader, existingValue as AnyUnion, serializer);
+    }
+  }
+  public AnyUnion ReadJson(Newtonsoft.Json.JsonReader reader, AnyUnion _o, Newtonsoft.Json.JsonSerializer serializer) {
+    if (_o == null) return null;
+    switch (_o.Type) {
+      default: break;
+      case Any.Monster: _o.Value = serializer.Deserialize<MyGame.Example.MonsterT>(reader); break;
+      case Any.TestSimpleTableWithEnum: _o.Value = serializer.Deserialize<MyGame.Example.TestSimpleTableWithEnumT>(reader); break;
+      case Any.MyGame_Example2_Monster: _o.Value = serializer.Deserialize<MyGame.Example2.MonsterT>(reader); break;
+    }
+    return _o;
+  }
+}
+
 
 }
index 3c24a77..07deadc 100644 (file)
@@ -5,6 +5,7 @@
 namespace MyGame.Example
 {
 
+[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))]
 public enum AnyAmbiguousAliases : byte
 {
   NONE = 0,
@@ -37,5 +38,48 @@ public class AnyAmbiguousAliasesUnion {
   }
 }
 
+public class AnyAmbiguousAliasesUnion_JsonConverter : Newtonsoft.Json.JsonConverter {
+  public override bool CanConvert(System.Type objectType) {
+    return objectType == typeof(AnyAmbiguousAliasesUnion) || objectType == typeof(System.Collections.Generic.List<AnyAmbiguousAliasesUnion>);
+  }
+  public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) {
+    var _olist = value as System.Collections.Generic.List<AnyAmbiguousAliasesUnion>;
+    if (_olist != null) {
+      writer.WriteStartArray();
+      foreach (var _o in _olist) { this.WriteJson(writer, _o, serializer); }
+      writer.WriteEndArray();
+    } else {
+      this.WriteJson(writer, value as AnyAmbiguousAliasesUnion, serializer);
+    }
+  }
+  public void WriteJson(Newtonsoft.Json.JsonWriter writer, AnyAmbiguousAliasesUnion _o, Newtonsoft.Json.JsonSerializer serializer) {
+    if (_o == null) return;
+    serializer.Serialize(writer, _o.Value);
+  }
+  public override object ReadJson(Newtonsoft.Json.JsonReader reader, System.Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) {
+    var _olist = existingValue as System.Collections.Generic.List<AnyAmbiguousAliasesUnion>;
+    if (_olist != null) {
+      for (var _j = 0; _j < _olist.Count; ++_j) {
+        reader.Read();
+        _olist[_j] = this.ReadJson(reader, _olist[_j], serializer);
+      }
+      reader.Read();
+      return _olist;
+    } else {
+      return this.ReadJson(reader, existingValue as AnyAmbiguousAliasesUnion, serializer);
+    }
+  }
+  public AnyAmbiguousAliasesUnion ReadJson(Newtonsoft.Json.JsonReader reader, AnyAmbiguousAliasesUnion _o, Newtonsoft.Json.JsonSerializer serializer) {
+    if (_o == null) return null;
+    switch (_o.Type) {
+      default: break;
+      case AnyAmbiguousAliases.M1: _o.Value = serializer.Deserialize<MyGame.Example.MonsterT>(reader); break;
+      case AnyAmbiguousAliases.M2: _o.Value = serializer.Deserialize<MyGame.Example.MonsterT>(reader); break;
+      case AnyAmbiguousAliases.M3: _o.Value = serializer.Deserialize<MyGame.Example.MonsterT>(reader); break;
+    }
+    return _o;
+  }
+}
+
 
 }
index 518e466..3594952 100644 (file)
@@ -5,6 +5,7 @@
 namespace MyGame.Example
 {
 
+[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))]
 public enum AnyUniqueAliases : byte
 {
   NONE = 0,
@@ -37,5 +38,48 @@ public class AnyUniqueAliasesUnion {
   }
 }
 
+public class AnyUniqueAliasesUnion_JsonConverter : Newtonsoft.Json.JsonConverter {
+  public override bool CanConvert(System.Type objectType) {
+    return objectType == typeof(AnyUniqueAliasesUnion) || objectType == typeof(System.Collections.Generic.List<AnyUniqueAliasesUnion>);
+  }
+  public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) {
+    var _olist = value as System.Collections.Generic.List<AnyUniqueAliasesUnion>;
+    if (_olist != null) {
+      writer.WriteStartArray();
+      foreach (var _o in _olist) { this.WriteJson(writer, _o, serializer); }
+      writer.WriteEndArray();
+    } else {
+      this.WriteJson(writer, value as AnyUniqueAliasesUnion, serializer);
+    }
+  }
+  public void WriteJson(Newtonsoft.Json.JsonWriter writer, AnyUniqueAliasesUnion _o, Newtonsoft.Json.JsonSerializer serializer) {
+    if (_o == null) return;
+    serializer.Serialize(writer, _o.Value);
+  }
+  public override object ReadJson(Newtonsoft.Json.JsonReader reader, System.Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) {
+    var _olist = existingValue as System.Collections.Generic.List<AnyUniqueAliasesUnion>;
+    if (_olist != null) {
+      for (var _j = 0; _j < _olist.Count; ++_j) {
+        reader.Read();
+        _olist[_j] = this.ReadJson(reader, _olist[_j], serializer);
+      }
+      reader.Read();
+      return _olist;
+    } else {
+      return this.ReadJson(reader, existingValue as AnyUniqueAliasesUnion, serializer);
+    }
+  }
+  public AnyUniqueAliasesUnion ReadJson(Newtonsoft.Json.JsonReader reader, AnyUniqueAliasesUnion _o, Newtonsoft.Json.JsonSerializer serializer) {
+    if (_o == null) return null;
+    switch (_o.Type) {
+      default: break;
+      case AnyUniqueAliases.M: _o.Value = serializer.Deserialize<MyGame.Example.MonsterT>(reader); break;
+      case AnyUniqueAliases.TS: _o.Value = serializer.Deserialize<MyGame.Example.TestSimpleTableWithEnumT>(reader); break;
+      case AnyUniqueAliases.M2: _o.Value = serializer.Deserialize<MyGame.Example2.MonsterT>(reader); break;
+    }
+    return _o;
+  }
+}
+
 
 }
index 1290d41..41c088d 100644 (file)
@@ -101,11 +101,17 @@ public struct ArrayStruct : IFlatbufferObject
 
 public class ArrayStructT
 {
+  [Newtonsoft.Json.JsonProperty("a")]
   public float A { get; set; }
+  [Newtonsoft.Json.JsonProperty("b")]
   public int[] B { get; set; }
+  [Newtonsoft.Json.JsonProperty("c")]
   public sbyte C { get; set; }
+  [Newtonsoft.Json.JsonProperty("d")]
   public MyGame.Example.NestedStructT[] D { get; set; }
+  [Newtonsoft.Json.JsonProperty("e")]
   public int E { get; set; }
+  [Newtonsoft.Json.JsonProperty("f")]
   public long[] F { get; set; }
 
   public ArrayStructT() {
index 759e511..faa83c6 100644 (file)
@@ -48,11 +48,19 @@ public struct ArrayTable : IFlatbufferObject
 
 public class ArrayTableT
 {
+  [Newtonsoft.Json.JsonProperty("a")]
   public MyGame.Example.ArrayStructT A { get; set; }
 
   public ArrayTableT() {
     this.A = new MyGame.Example.ArrayStructT();
   }
+
+  public static ArrayTableT DeserializeFromJson(string jsonText) {
+    return Newtonsoft.Json.JsonConvert.DeserializeObject<ArrayTableT>(jsonText);
+  }
+  public string SerializeToJson() {
+    return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented);
+  }
 }
 
 
index 5981cf8..1137a27 100644 (file)
@@ -6,6 +6,7 @@ namespace MyGame.Example
 {
 
 /// Composite components of Monster color.
+[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))]
 [System.FlagsAttribute]
 public enum Color : byte
 {
index 13bcb82..4311112 100644 (file)
@@ -593,50 +593,142 @@ public struct Monster : IFlatbufferObject
 
 public class MonsterT
 {
+  [Newtonsoft.Json.JsonProperty("pos")]
   public MyGame.Example.Vec3T Pos { get; set; }
+  [Newtonsoft.Json.JsonProperty("mana")]
   public short Mana { get; set; }
+  [Newtonsoft.Json.JsonProperty("hp")]
   public short Hp { get; set; }
+  [Newtonsoft.Json.JsonProperty("name")]
   public string Name { get; set; }
+  [Newtonsoft.Json.JsonProperty("inventory")]
   public List<byte> Inventory { get; set; }
+  [Newtonsoft.Json.JsonProperty("color")]
   public MyGame.Example.Color Color { get; set; }
+  [Newtonsoft.Json.JsonProperty("test_type")]
+  private MyGame.Example.Any TestType {
+    get {
+      return this.Test != null ? this.Test.Type : MyGame.Example.Any.NONE;
+    }
+    set {
+      this.Test = new MyGame.Example.AnyUnion();
+      this.Test.Type = value;
+    }
+  }
+  [Newtonsoft.Json.JsonProperty("test")]
+  [Newtonsoft.Json.JsonConverter(typeof(MyGame.Example.AnyUnion_JsonConverter))]
   public MyGame.Example.AnyUnion Test { get; set; }
+  [Newtonsoft.Json.JsonProperty("test4")]
   public List<MyGame.Example.TestT> Test4 { get; set; }
+  [Newtonsoft.Json.JsonProperty("testarrayofstring")]
   public List<string> Testarrayofstring { get; set; }
+  [Newtonsoft.Json.JsonProperty("testarrayoftables")]
   public List<MyGame.Example.MonsterT> Testarrayoftables { get; set; }
+  [Newtonsoft.Json.JsonProperty("enemy")]
   public MyGame.Example.MonsterT Enemy { get; set; }
+  [Newtonsoft.Json.JsonProperty("testnestedflatbuffer")]
   public List<byte> Testnestedflatbuffer { get; set; }
+  [Newtonsoft.Json.JsonProperty("testempty")]
   public MyGame.Example.StatT Testempty { get; set; }
+  [Newtonsoft.Json.JsonProperty("testbool")]
   public bool Testbool { get; set; }
+  [Newtonsoft.Json.JsonProperty("testhashs32_fnv1")]
+  [Newtonsoft.Json.JsonIgnore()]
   public int Testhashs32Fnv1 { get; set; }
+  [Newtonsoft.Json.JsonProperty("testhashu32_fnv1")]
+  [Newtonsoft.Json.JsonIgnore()]
   public uint Testhashu32Fnv1 { get; set; }
+  [Newtonsoft.Json.JsonProperty("testhashs64_fnv1")]
+  [Newtonsoft.Json.JsonIgnore()]
   public long Testhashs64Fnv1 { get; set; }
+  [Newtonsoft.Json.JsonProperty("testhashu64_fnv1")]
+  [Newtonsoft.Json.JsonIgnore()]
   public ulong Testhashu64Fnv1 { get; set; }
+  [Newtonsoft.Json.JsonProperty("testhashs32_fnv1a")]
+  [Newtonsoft.Json.JsonIgnore()]
   public int Testhashs32Fnv1a { get; set; }
+  [Newtonsoft.Json.JsonProperty("testhashu32_fnv1a")]
+  [Newtonsoft.Json.JsonIgnore()]
   public uint Testhashu32Fnv1a { get; set; }
+  [Newtonsoft.Json.JsonProperty("testhashs64_fnv1a")]
+  [Newtonsoft.Json.JsonIgnore()]
   public long Testhashs64Fnv1a { get; set; }
+  [Newtonsoft.Json.JsonProperty("testhashu64_fnv1a")]
+  [Newtonsoft.Json.JsonIgnore()]
   public ulong Testhashu64Fnv1a { get; set; }
+  [Newtonsoft.Json.JsonProperty("testarrayofbools")]
   public List<bool> Testarrayofbools { get; set; }
+  [Newtonsoft.Json.JsonProperty("testf")]
   public float Testf { get; set; }
+  [Newtonsoft.Json.JsonProperty("testf2")]
   public float Testf2 { get; set; }
+  [Newtonsoft.Json.JsonProperty("testf3")]
   public float Testf3 { get; set; }
+  [Newtonsoft.Json.JsonProperty("testarrayofstring2")]
   public List<string> Testarrayofstring2 { get; set; }
+  [Newtonsoft.Json.JsonProperty("testarrayofsortedstruct")]
   public List<MyGame.Example.AbilityT> Testarrayofsortedstruct { get; set; }
+  [Newtonsoft.Json.JsonProperty("flex")]
   public List<byte> Flex { get; set; }
+  [Newtonsoft.Json.JsonProperty("test5")]
   public List<MyGame.Example.TestT> Test5 { get; set; }
+  [Newtonsoft.Json.JsonProperty("vector_of_longs")]
   public List<long> VectorOfLongs { get; set; }
+  [Newtonsoft.Json.JsonProperty("vector_of_doubles")]
   public List<double> VectorOfDoubles { get; set; }
+  [Newtonsoft.Json.JsonProperty("parent_namespace_test")]
   public MyGame.InParentNamespaceT ParentNamespaceTest { get; set; }
+  [Newtonsoft.Json.JsonProperty("vector_of_referrables")]
   public List<MyGame.Example.ReferrableT> VectorOfReferrables { get; set; }
+  [Newtonsoft.Json.JsonProperty("single_weak_reference")]
+  [Newtonsoft.Json.JsonIgnore()]
   public ulong SingleWeakReference { get; set; }
+  [Newtonsoft.Json.JsonProperty("vector_of_weak_references")]
+  [Newtonsoft.Json.JsonIgnore()]
   public List<ulong> VectorOfWeakReferences { get; set; }
+  [Newtonsoft.Json.JsonProperty("vector_of_strong_referrables")]
   public List<MyGame.Example.ReferrableT> VectorOfStrongReferrables { get; set; }
+  [Newtonsoft.Json.JsonProperty("co_owning_reference")]
+  [Newtonsoft.Json.JsonIgnore()]
   public ulong CoOwningReference { get; set; }
+  [Newtonsoft.Json.JsonProperty("vector_of_co_owning_references")]
+  [Newtonsoft.Json.JsonIgnore()]
   public List<ulong> VectorOfCoOwningReferences { get; set; }
+  [Newtonsoft.Json.JsonProperty("non_owning_reference")]
+  [Newtonsoft.Json.JsonIgnore()]
   public ulong NonOwningReference { get; set; }
+  [Newtonsoft.Json.JsonProperty("vector_of_non_owning_references")]
+  [Newtonsoft.Json.JsonIgnore()]
   public List<ulong> VectorOfNonOwningReferences { get; set; }
+  [Newtonsoft.Json.JsonProperty("any_unique_type")]
+  private MyGame.Example.AnyUniqueAliases AnyUniqueType {
+    get {
+      return this.AnyUnique != null ? this.AnyUnique.Type : MyGame.Example.AnyUniqueAliases.NONE;
+    }
+    set {
+      this.AnyUnique = new MyGame.Example.AnyUniqueAliasesUnion();
+      this.AnyUnique.Type = value;
+    }
+  }
+  [Newtonsoft.Json.JsonProperty("any_unique")]
+  [Newtonsoft.Json.JsonConverter(typeof(MyGame.Example.AnyUniqueAliasesUnion_JsonConverter))]
   public MyGame.Example.AnyUniqueAliasesUnion AnyUnique { get; set; }
+  [Newtonsoft.Json.JsonProperty("any_ambiguous_type")]
+  private MyGame.Example.AnyAmbiguousAliases AnyAmbiguousType {
+    get {
+      return this.AnyAmbiguous != null ? this.AnyAmbiguous.Type : MyGame.Example.AnyAmbiguousAliases.NONE;
+    }
+    set {
+      this.AnyAmbiguous = new MyGame.Example.AnyAmbiguousAliasesUnion();
+      this.AnyAmbiguous.Type = value;
+    }
+  }
+  [Newtonsoft.Json.JsonProperty("any_ambiguous")]
+  [Newtonsoft.Json.JsonConverter(typeof(MyGame.Example.AnyAmbiguousAliasesUnion_JsonConverter))]
   public MyGame.Example.AnyAmbiguousAliasesUnion AnyAmbiguous { get; set; }
+  [Newtonsoft.Json.JsonProperty("vector_of_enums")]
   public List<MyGame.Example.Color> VectorOfEnums { get; set; }
+  [Newtonsoft.Json.JsonProperty("signed_enum")]
   public MyGame.Example.Race SignedEnum { get; set; }
 
   public MonsterT() {
@@ -686,6 +778,13 @@ public class MonsterT
     this.VectorOfEnums = null;
     this.SignedEnum = MyGame.Example.Race.None;
   }
+
+  public static MonsterT DeserializeFromJson(string jsonText) {
+    return Newtonsoft.Json.JsonConvert.DeserializeObject<MonsterT>(jsonText);
+  }
+  public string SerializeToJson() {
+    return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented);
+  }
 }
 
 
index 190ffa0..13e3498 100644 (file)
@@ -70,9 +70,13 @@ public struct NestedStruct : IFlatbufferObject
 
 public class NestedStructT
 {
+  [Newtonsoft.Json.JsonProperty("a")]
   public int[] A { get; set; }
+  [Newtonsoft.Json.JsonProperty("b")]
   public MyGame.Example.TestEnum B { get; set; }
+  [Newtonsoft.Json.JsonProperty("c")]
   public MyGame.Example.TestEnum[] C { get; set; }
+  [Newtonsoft.Json.JsonProperty("d")]
   public long[] D { get; set; }
 
   public NestedStructT() {
index 8fa2178..8a1959a 100644 (file)
@@ -5,6 +5,7 @@
 namespace MyGame.Example
 {
 
+[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))]
 public enum Race : sbyte
 {
   None = -1,
index 43382a0..520af93 100644 (file)
@@ -78,6 +78,8 @@ public struct Referrable : IFlatbufferObject
 
 public class ReferrableT
 {
+  [Newtonsoft.Json.JsonProperty("id")]
+  [Newtonsoft.Json.JsonIgnore()]
   public ulong Id { get; set; }
 
   public ReferrableT() {
index 0c7160d..9f98d61 100644 (file)
@@ -73,8 +73,11 @@ public struct Stat : IFlatbufferObject
 
 public class StatT
 {
+  [Newtonsoft.Json.JsonProperty("id")]
   public string Id { get; set; }
+  [Newtonsoft.Json.JsonProperty("val")]
   public long Val { get; set; }
+  [Newtonsoft.Json.JsonProperty("count")]
   public ushort Count { get; set; }
 
   public StatT() {
index caac6fe..a6419ed 100644 (file)
@@ -48,7 +48,9 @@ public struct Test : IFlatbufferObject
 
 public class TestT
 {
+  [Newtonsoft.Json.JsonProperty("a")]
   public short A { get; set; }
+  [Newtonsoft.Json.JsonProperty("b")]
   public sbyte B { get; set; }
 
   public TestT() {
index 22e83b3..6dfd6b5 100644 (file)
@@ -5,6 +5,7 @@
 namespace MyGame.Example
 {
 
+[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))]
 public enum TestEnum : sbyte
 {
   A = 0,
index 98d56d1..82c86cb 100644 (file)
@@ -53,6 +53,7 @@ internal partial struct TestSimpleTableWithEnum : IFlatbufferObject
 
 internal partial class TestSimpleTableWithEnumT
 {
+  [Newtonsoft.Json.JsonProperty("color")]
   public MyGame.Example.Color Color { get; set; }
 
   public TestSimpleTableWithEnumT() {
index b74b8c9..4987640 100644 (file)
@@ -162,17 +162,29 @@ public struct TypeAliases : IFlatbufferObject
 
 public class TypeAliasesT
 {
+  [Newtonsoft.Json.JsonProperty("i8")]
   public sbyte I8 { get; set; }
+  [Newtonsoft.Json.JsonProperty("u8")]
   public byte U8 { get; set; }
+  [Newtonsoft.Json.JsonProperty("i16")]
   public short I16 { get; set; }
+  [Newtonsoft.Json.JsonProperty("u16")]
   public ushort U16 { get; set; }
+  [Newtonsoft.Json.JsonProperty("i32")]
   public int I32 { get; set; }
+  [Newtonsoft.Json.JsonProperty("u32")]
   public uint U32 { get; set; }
+  [Newtonsoft.Json.JsonProperty("i64")]
   public long I64 { get; set; }
+  [Newtonsoft.Json.JsonProperty("u64")]
   public ulong U64 { get; set; }
+  [Newtonsoft.Json.JsonProperty("f32")]
   public float F32 { get; set; }
+  [Newtonsoft.Json.JsonProperty("f64")]
   public double F64 { get; set; }
+  [Newtonsoft.Json.JsonProperty("v8")]
   public List<sbyte> V8 { get; set; }
+  [Newtonsoft.Json.JsonProperty("vf64")]
   public List<double> Vf64 { get; set; }
 
   public TypeAliasesT() {
index 9c106f5..4a9bf0d 100644 (file)
@@ -73,11 +73,17 @@ public struct Vec3 : IFlatbufferObject
 
 public class Vec3T
 {
+  [Newtonsoft.Json.JsonProperty("x")]
   public float X { get; set; }
+  [Newtonsoft.Json.JsonProperty("y")]
   public float Y { get; set; }
+  [Newtonsoft.Json.JsonProperty("z")]
   public float Z { get; set; }
+  [Newtonsoft.Json.JsonProperty("test1")]
   public double Test1 { get; set; }
+  [Newtonsoft.Json.JsonProperty("test2")]
   public MyGame.Example.Color Test2 { get; set; }
+  [Newtonsoft.Json.JsonProperty("test3")]
   public MyGame.Example.TestT Test3 { get; set; }
 
   public Vec3T() {
index b85426d..7005736 100644 (file)
@@ -151,15 +151,25 @@ public struct MonsterExtra : IFlatbufferObject
 
 public class MonsterExtraT
 {
+  [Newtonsoft.Json.JsonProperty("d0")]
   public double D0 { get; set; }
+  [Newtonsoft.Json.JsonProperty("d1")]
   public double D1 { get; set; }
+  [Newtonsoft.Json.JsonProperty("d2")]
   public double D2 { get; set; }
+  [Newtonsoft.Json.JsonProperty("d3")]
   public double D3 { get; set; }
+  [Newtonsoft.Json.JsonProperty("f0")]
   public float F0 { get; set; }
+  [Newtonsoft.Json.JsonProperty("f1")]
   public float F1 { get; set; }
+  [Newtonsoft.Json.JsonProperty("f2")]
   public float F2 { get; set; }
+  [Newtonsoft.Json.JsonProperty("f3")]
   public float F3 { get; set; }
+  [Newtonsoft.Json.JsonProperty("dvec")]
   public List<double> Dvec { get; set; }
+  [Newtonsoft.Json.JsonProperty("fvec")]
   public List<float> Fvec { get; set; }
 
   public MonsterExtraT() {
@@ -174,6 +184,13 @@ public class MonsterExtraT
     this.Dvec = null;
     this.Fvec = null;
   }
+
+  public static MonsterExtraT DeserializeFromJson(string jsonText) {
+    return Newtonsoft.Json.JsonConvert.DeserializeObject<MonsterExtraT>(jsonText);
+  }
+  public string SerializeToJson() {
+    return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented);
+  }
 }
 
 
index 7980f04..d8d18ce 100644 (file)
@@ -28,31 +28,32 @@ if NOT "%commandline%"=="%commandline:--cpp-std c++0x=%" (
 )
 
 set TEST_CPP_FLAGS=--gen-compare --cpp-ptr-type flatbuffers::unique_ptr %TEST_CPP_FLAGS%
+set TEST_CS_FLAGS=--cs-gen-json-serializer
 set TEST_BASE_FLAGS=--reflect-names --gen-mutable --gen-object-api
 set TEST_NOINCL_FLAGS=%TEST_BASE_FLAGS% --no-includes --no-fb-import
 
 ..\%buildtype%\flatc.exe --binary --cpp --java --kotlin --csharp --dart --go --lobster --lua --js --ts --php --rust --grpc ^
-%TEST_NOINCL_FLAGS% %TEST_CPP_FLAGS% -I include_test monster_test.fbs monsterdata_test.json || goto FAIL
+%TEST_NOINCL_FLAGS% %TEST_CPP_FLAGS% %TEST_CS_FLAGS% -I include_test monster_test.fbs monsterdata_test.json || goto FAIL
 
 ..\%buildtype%\flatc.exe --python %TEST_BASE_FLAGS% --no-fb-import -I include_test monster_test.fbs monsterdata_test.json || goto FAIL
 
 ..\%buildtype%\flatc.exe --binary --cpp --java --csharp --dart --go --lobster --lua --js --ts --php --python --rust ^
-%TEST_NOINCL_FLAGS% %TEST_CPP_FLAGS% -o namespace_test namespace_test/namespace_test1.fbs namespace_test/namespace_test2.fbs || goto FAIL
+%TEST_NOINCL_FLAGS% %TEST_CPP_FLAGS% %TEST_CS_FLAGS% -o namespace_test namespace_test/namespace_test1.fbs namespace_test/namespace_test2.fbs || goto FAIL
 
-..\%buildtype%\flatc.exe --cpp --java --csharp --js --ts --php %TEST_BASE_FLAGS% %TEST_CPP_FLAGS% -o union_vector ./union_vector/union_vector.fbs || goto FAIL
+..\%buildtype%\flatc.exe --cpp --java --csharp --js --ts --php %TEST_BASE_FLAGS% %TEST_CPP_FLAGS% %TEST_CS_FLAGS% -o union_vector ./union_vector/union_vector.fbs || goto FAIL
 ..\%buildtype%\flatc.exe --rust -I include_test -o include_test include_test/include_test1.fbs || goto FAIL
 ..\%buildtype%\flatc.exe --rust -I include_test -o include_test/sub include_test/sub/include_test2.fbs || goto FAIL
 ..\%buildtype%\flatc.exe -b --schema --bfbs-comments --bfbs-builtins -I include_test monster_test.fbs || goto FAIL
 ..\%buildtype%\flatc.exe --cpp --bfbs-comments --bfbs-builtins --bfbs-gen-embed %TEST_NOINCL_FLAGS% %TEST_CPP_FLAGS% -I include_test monster_test.fbs || goto FAIL
 ..\%buildtype%\flatc.exe -b --schema --bfbs-comments --bfbs-builtins -I include_test arrays_test.fbs || goto FAIL
 ..\%buildtype%\flatc.exe --jsonschema --schema -I include_test monster_test.fbs || goto FAIL
-..\%buildtype%\flatc.exe --cpp --java --csharp --jsonschema %TEST_NOINCL_FLAGS% %TEST_CPP_FLAGS% --scoped-enums arrays_test.fbs || goto FAIL
+..\%buildtype%\flatc.exe --cpp --java --csharp --jsonschema %TEST_NOINCL_FLAGS% %TEST_CPP_FLAGS% %TEST_CS_FLAGS% --scoped-enums arrays_test.fbs || goto FAIL
 ..\%buildtype%\flatc.exe --python %TEST_BASE_FLAGS% arrays_test.fbs || goto FAIL
 ..\%buildtype%\flatc.exe --cpp %TEST_BASE_FLAGS% --cpp-ptr-type flatbuffers::unique_ptr native_type_test.fbs || goto FAIL
 
 if NOT "%MONSTER_EXTRA%"=="skip" (
   @echo Generate MosterExtra
-  ..\%buildtype%\flatc.exe --cpp --java --csharp %TEST_NOINCL_FLAGS% %TEST_CPP_FLAGS% monster_extra.fbs monsterdata_extra.json || goto FAIL
+  ..\%buildtype%\flatc.exe --cpp --java --csharp %TEST_NOINCL_FLAGS% %TEST_CPP_FLAGS% %TEST_CS_FLAGS% monster_extra.fbs monsterdata_extra.json || goto FAIL
   ..\%buildtype%\flatc.exe --python %TEST_BASE_FLAGS% monster_extra.fbs monsterdata_extra.json || goto FAIL
 ) else (
   @echo monster_extra.fbs skipped (the strtod function from MSVC2013 or older doesn't support NaN/Inf arguments)
index 04c4e62..bce5274 100755 (executable)
@@ -25,26 +25,27 @@ else
 fi
 
 TEST_CPP_FLAGS="--gen-compare --cpp-ptr-type flatbuffers::unique_ptr $TEST_CPP_FLAGS"
+TEST_CS_FLAGS="--cs-gen-json-serializer"
 TEST_BASE_FLAGS="--reflect-names --gen-mutable --gen-object-api"
 TEST_NOINCL_FLAGS="$TEST_BASE_FLAGS --no-includes --no-fb-import"
 
 ../flatc --binary --cpp --java --kotlin  --csharp --dart --go --lobster --lua --js --ts --php --rust --grpc \
-$TEST_NOINCL_FLAGS $TEST_CPP_FLAGS -I include_test monster_test.fbs monsterdata_test.json
+$TEST_NOINCL_FLAGS $TEST_CPP_FLAGS $TEST_CS_FLAGS -I include_test monster_test.fbs monsterdata_test.json
 
 ../flatc --python $TEST_BASE_FLAGS -I include_test monster_test.fbs monsterdata_test.json
 
 ../flatc --cpp --java --kotlin --csharp --dart --go --binary --lobster --lua --js --ts --php --python --rust \
-$TEST_NOINCL_FLAGS $TEST_CPP_FLAGS -o namespace_test namespace_test/namespace_test1.fbs namespace_test/namespace_test2.fbs
+$TEST_NOINCL_FLAGS $TEST_CPP_FLAGS $TEST_CS_FLAGS -o namespace_test namespace_test/namespace_test1.fbs namespace_test/namespace_test2.fbs
 
-../flatc --cpp --java --kotlin --csharp --js --ts --php $TEST_BASE_FLAGS $TEST_CPP_FLAGS -o union_vector ./union_vector/union_vector.fbs
+../flatc --cpp --java --kotlin --csharp --js --ts --php $TEST_BASE_FLAGS $TEST_CPP_FLAGS $TEST_CS_FLAGS -o union_vector ./union_vector/union_vector.fbs
 ../flatc --rust -I include_test -o include_test include_test/include_test1.fbs
 ../flatc --rust -I include_test -o include_test/sub include_test/sub/include_test2.fbs
 ../flatc -b --schema --bfbs-comments --bfbs-builtins -I include_test monster_test.fbs
 ../flatc --cpp --bfbs-comments --bfbs-builtins --bfbs-gen-embed $TEST_NOINCL_FLAGS $TEST_CPP_FLAGS -I include_test monster_test.fbs
 ../flatc -b --schema --bfbs-comments --bfbs-builtins -I include_test arrays_test.fbs
 ../flatc --jsonschema --schema -I include_test monster_test.fbs
-../flatc --cpp --java --kotlin --csharp --python $TEST_NOINCL_FLAGS $TEST_CPP_FLAGS monster_extra.fbs monsterdata_extra.json
-../flatc --cpp --java --csharp --jsonschema $TEST_NOINCL_FLAGS $TEST_CPP_FLAGS --scoped-enums arrays_test.fbs
+../flatc --cpp --java --kotlin --csharp --python $TEST_NOINCL_FLAGS $TEST_CPP_FLAGS $TEST_CS_FLAGS monster_extra.fbs monsterdata_extra.json
+../flatc --cpp --java --csharp --jsonschema $TEST_NOINCL_FLAGS $TEST_CPP_FLAGS $TEST_CS_FLAGS --scoped-enums arrays_test.fbs
 ../flatc --python $TEST_BASE_FLAGS arrays_test.fbs
 ../flatc --dart monster_extra.fbs
 
index d3028b5..eb40080 100644 (file)
@@ -4,7 +4,7 @@
     y: "2",
     z: 3,
     test1: 3,
-    test2: Green,
+    test2: "Green",
     test3: {
       a: 5,
       b: 6
@@ -31,7 +31,7 @@
       0,
       1.7976931348623157e+308
   ],
-  test_type: Monster,
+  test_type: "Monster",
   test: {
     name: "Fred",
     pos: null
index ff44023..bb17d7b 100644 (file)
@@ -5,6 +5,7 @@
 namespace NamespaceA.NamespaceB
 {
 
+[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))]
 public enum EnumInNestedNS : sbyte
 {
   A = 0,
index 9f6d8dc..6fa9dd3 100644 (file)
@@ -47,7 +47,9 @@ public struct StructInNestedNS : IFlatbufferObject
 
 public class StructInNestedNST
 {
+  [Newtonsoft.Json.JsonProperty("a")]
   public int A { get; set; }
+  [Newtonsoft.Json.JsonProperty("b")]
   public int B { get; set; }
 
   public StructInNestedNST() {
index 88d0342..da0e6b7 100644 (file)
@@ -53,6 +53,7 @@ public struct TableInNestedNS : IFlatbufferObject
 
 public class TableInNestedNST
 {
+  [Newtonsoft.Json.JsonProperty("foo")]
   public int Foo { get; set; }
 
   public TableInNestedNST() {
index 57d7741..9c38134 100644 (file)
@@ -53,6 +53,7 @@ public struct SecondTableInA : IFlatbufferObject
 
 public class SecondTableInAT
 {
+  [Newtonsoft.Json.JsonProperty("refer_to_c")]
   public NamespaceC.TableInCT ReferToC { get; set; }
 
   public SecondTableInAT() {
index 759e53e..8484241 100644 (file)
@@ -55,8 +55,11 @@ public struct TableInFirstNS : IFlatbufferObject
 
 public class TableInFirstNST
 {
+  [Newtonsoft.Json.JsonProperty("foo_table")]
   public NamespaceA.NamespaceB.TableInNestedNST FooTable { get; set; }
+  [Newtonsoft.Json.JsonProperty("foo_enum")]
   public NamespaceA.NamespaceB.EnumInNestedNS FooEnum { get; set; }
+  [Newtonsoft.Json.JsonProperty("foo_struct")]
   public NamespaceA.NamespaceB.StructInNestedNST FooStruct { get; set; }
 
   public TableInFirstNST() {
index 358ca59..040a916 100644 (file)
@@ -60,7 +60,9 @@ public struct TableInC : IFlatbufferObject
 
 public class TableInCT
 {
+  [Newtonsoft.Json.JsonProperty("refer_to_a1")]
   public NamespaceA.TableInFirstNST ReferToA1 { get; set; }
+  [Newtonsoft.Json.JsonProperty("refer_to_a2")]
   public NamespaceA.SecondTableInAT ReferToA2 { get; set; }
 
   public TableInCT() {
index d36555d..cebc0c7 100644 (file)
@@ -50,6 +50,7 @@ public struct Attacker : IFlatbufferObject
 
 public class AttackerT
 {
+  [Newtonsoft.Json.JsonProperty("sword_attack_damage")]
   public int SwordAttackDamage { get; set; }
 
   public AttackerT() {
index c40c0df..3f80cdf 100644 (file)
@@ -39,6 +39,7 @@ public struct BookReader : IFlatbufferObject
 
 public class BookReaderT
 {
+  [Newtonsoft.Json.JsonProperty("books_read")]
   public int BooksRead { get; set; }
 
   public BookReaderT() {
index cb16e6f..d067e22 100644 (file)
@@ -2,6 +2,7 @@
 //  automatically generated by the FlatBuffers compiler, do not modify
 // </auto-generated>
 
+[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))]
 public enum Character : byte
 {
   NONE = 0,
@@ -43,3 +44,49 @@ public class CharacterUnion {
   }
 }
 
+public class CharacterUnion_JsonConverter : Newtonsoft.Json.JsonConverter {
+  public override bool CanConvert(System.Type objectType) {
+    return objectType == typeof(CharacterUnion) || objectType == typeof(System.Collections.Generic.List<CharacterUnion>);
+  }
+  public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) {
+    var _olist = value as System.Collections.Generic.List<CharacterUnion>;
+    if (_olist != null) {
+      writer.WriteStartArray();
+      foreach (var _o in _olist) { this.WriteJson(writer, _o, serializer); }
+      writer.WriteEndArray();
+    } else {
+      this.WriteJson(writer, value as CharacterUnion, serializer);
+    }
+  }
+  public void WriteJson(Newtonsoft.Json.JsonWriter writer, CharacterUnion _o, Newtonsoft.Json.JsonSerializer serializer) {
+    if (_o == null) return;
+    serializer.Serialize(writer, _o.Value);
+  }
+  public override object ReadJson(Newtonsoft.Json.JsonReader reader, System.Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) {
+    var _olist = existingValue as System.Collections.Generic.List<CharacterUnion>;
+    if (_olist != null) {
+      for (var _j = 0; _j < _olist.Count; ++_j) {
+        reader.Read();
+        _olist[_j] = this.ReadJson(reader, _olist[_j], serializer);
+      }
+      reader.Read();
+      return _olist;
+    } else {
+      return this.ReadJson(reader, existingValue as CharacterUnion, serializer);
+    }
+  }
+  public CharacterUnion ReadJson(Newtonsoft.Json.JsonReader reader, CharacterUnion _o, Newtonsoft.Json.JsonSerializer serializer) {
+    if (_o == null) return null;
+    switch (_o.Type) {
+      default: break;
+      case Character.MuLan: _o.Value = serializer.Deserialize<AttackerT>(reader); break;
+      case Character.Rapunzel: _o.Value = serializer.Deserialize<RapunzelT>(reader); break;
+      case Character.Belle: _o.Value = serializer.Deserialize<BookReaderT>(reader); break;
+      case Character.BookFan: _o.Value = serializer.Deserialize<BookReaderT>(reader); break;
+      case Character.Other: _o.Value = serializer.Deserialize<string>(reader); break;
+      case Character.Unused: _o.Value = serializer.Deserialize<string>(reader); break;
+    }
+    return _o;
+  }
+}
+
index 7fc1038..a19bb25 100644 (file)
@@ -146,12 +146,50 @@ public struct Movie : IFlatbufferObject
 
 public class MovieT
 {
+  [Newtonsoft.Json.JsonProperty("main_character_type")]
+  private Character MainCharacterType {
+    get {
+      return this.MainCharacter != null ? this.MainCharacter.Type : Character.NONE;
+    }
+    set {
+      this.MainCharacter = new CharacterUnion();
+      this.MainCharacter.Type = value;
+    }
+  }
+  [Newtonsoft.Json.JsonProperty("main_character")]
+  [Newtonsoft.Json.JsonConverter(typeof(CharacterUnion_JsonConverter))]
   public CharacterUnion MainCharacter { get; set; }
+  [Newtonsoft.Json.JsonProperty("characters_type")]
+  private Character[] CharactersType {
+    get {
+      if (this.Characters == null) return null;
+      var _o = new Character[this.Characters.Count];
+      for (var _j = 0; _j < _o.Length; ++_j) { _o[_j] = this.Characters[_j].Type; }
+      return _o;
+    }
+    set {
+      this.Characters = new List<CharacterUnion>();
+      for (var _j = 0; _j < value.Length; ++_j) {
+        var _o = new CharacterUnion();
+        _o.Type = value[_j];
+        this.Characters.Add(_o);
+      }
+    }
+  }
+  [Newtonsoft.Json.JsonProperty("characters")]
+  [Newtonsoft.Json.JsonConverter(typeof(CharacterUnion_JsonConverter))]
   public List<CharacterUnion> Characters { get; set; }
 
   public MovieT() {
     this.MainCharacter = null;
     this.Characters = null;
   }
+
+  public static MovieT DeserializeFromJson(string jsonText) {
+    return Newtonsoft.Json.JsonConvert.DeserializeObject<MovieT>(jsonText);
+  }
+  public string SerializeToJson() {
+    return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented);
+  }
 }
 
index 3cb6f19..e5ffff8 100644 (file)
@@ -39,6 +39,7 @@ public struct Rapunzel : IFlatbufferObject
 
 public class RapunzelT
 {
+  [Newtonsoft.Json.JsonProperty("hair_length")]
   public int HairLength { get; set; }
 
   public RapunzelT() {