diff --git a/scripts/generate_code.py b/scripts/generate_code.py index c72d18a2a..1e29d755f 100755 --- a/scripts/generate_code.py +++ b/scripts/generate_code.py @@ -407,6 +407,13 @@ type_field_collsion_schema = "type_field_collsion.fbs" flatc(["--csharp", "--gen-object-api"], schema=type_field_collsion_schema) +# Union / value collision +flatc( + CS_OPTS + ["--gen-object-api", "--gen-onefile"], + prefix="union_value_collsion", + schema="union_value_collision.fbs" +) + # Generate string/vector default code for tests flatc(RUST_OPTS, prefix="more_defaults", schema="more_defaults.fbs") diff --git a/src/idl_gen_csharp.cpp b/src/idl_gen_csharp.cpp index 813ad0a65..7f5ca0702 100644 --- a/src/idl_gen_csharp.cpp +++ b/src/idl_gen_csharp.cpp @@ -1525,7 +1525,7 @@ class CSharpGenerator : public BaseGenerator { " _o, " "Newtonsoft.Json.JsonSerializer serializer) {\n"; code += " if (_o == null) return;\n"; - code += " serializer.Serialize(writer, _o.Value);\n"; + code += " serializer.Serialize(writer, _o." + class_member + ");\n"; code += " }\n"; code += " public override object ReadJson(Newtonsoft.Json.JsonReader " @@ -1562,8 +1562,8 @@ class CSharpGenerator : public BaseGenerator { code += " default: break;\n"; } else { auto type_name = GenTypeGet_ObjectAPI(ev.union_type, opts); - code += " case " + Name(enum_def) + "." + Name(ev) + - ": _o.Value = serializer.Deserialize<" + type_name + + code += " case " + Name(enum_def) + "." + Name(ev) + ": _o." + + class_member + " = serializer.Deserialize<" + type_name + ">(reader); break;\n"; } } @@ -1586,7 +1586,7 @@ class CSharpGenerator : public BaseGenerator { auto &code = *code_ptr; std::string varialbe_name = "_o." + camel_name; std::string class_member = "Value"; - if (class_member == camel_name) class_member += "_"; + if (class_member == enum_def.name) class_member += "_"; std::string type_suffix = ""; std::string func_suffix = "()"; std::string indent = " "; diff --git a/tests/FlatBuffers.Test/FlatBuffers.Core.Test.csproj b/tests/FlatBuffers.Test/FlatBuffers.Core.Test.csproj index a7697855d..a82b07af3 100644 --- a/tests/FlatBuffers.Test/FlatBuffers.Core.Test.csproj +++ b/tests/FlatBuffers.Test/FlatBuffers.Core.Test.csproj @@ -169,6 +169,9 @@ nested_namespace_test\nested_namespace_test3_generated.cs + + union_value_collsion\union_value_collision_generated.cs + diff --git a/tests/union_value_collision.fbs b/tests/union_value_collision.fbs new file mode 100644 index 000000000..2e3224502 --- /dev/null +++ b/tests/union_value_collision.fbs @@ -0,0 +1,17 @@ +namespace union_value_collsion; + +table IntValue { + value:int; +} + +union Value { IntValue } + +union Other { IntValue } + +// This table tests collsions of Unions and fields named value. +table Collision { + some_value : Value; + value : Other; +} + +root_type Collision; \ No newline at end of file diff --git a/tests/union_value_collsion/union_value_collision_generated.cs b/tests/union_value_collsion/union_value_collision_generated.cs new file mode 100644 index 000000000..ce0acde57 --- /dev/null +++ b/tests/union_value_collsion/union_value_collision_generated.cs @@ -0,0 +1,331 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +namespace union_value_collsion +{ + +using global::System; +using global::System.Collections.Generic; +using global::Google.FlatBuffers; + +[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] +public enum Value : byte +{ + NONE = 0, + IntValue = 1, +}; + +public class ValueUnion { + public Value Type { get; set; } + public object Value_ { get; set; } + + public ValueUnion() { + this.Type = Value.NONE; + this.Value_ = null; + } + + public T As() where T : class { return this.Value_ as T; } + public union_value_collsion.IntValueT AsIntValue() { return this.As(); } + public static ValueUnion FromIntValue(union_value_collsion.IntValueT _intvalue) { return new ValueUnion{ Type = Value.IntValue, Value_ = _intvalue }; } + + public static int Pack(Google.FlatBuffers.FlatBufferBuilder builder, ValueUnion _o) { + switch (_o.Type) { + default: return 0; + case Value.IntValue: return union_value_collsion.IntValue.Pack(builder, _o.AsIntValue()).Value; + } + } +} + +public class ValueUnion_JsonConverter : Newtonsoft.Json.JsonConverter { + public override bool CanConvert(System.Type objectType) { + return objectType == typeof(ValueUnion) || objectType == typeof(System.Collections.Generic.List); + } + public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) { + var _olist = value as System.Collections.Generic.List; + if (_olist != null) { + writer.WriteStartArray(); + foreach (var _o in _olist) { this.WriteJson(writer, _o, serializer); } + writer.WriteEndArray(); + } else { + this.WriteJson(writer, value as ValueUnion, serializer); + } + } + public void WriteJson(Newtonsoft.Json.JsonWriter writer, ValueUnion _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; + 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 ValueUnion, serializer); + } + } + public ValueUnion ReadJson(Newtonsoft.Json.JsonReader reader, ValueUnion _o, Newtonsoft.Json.JsonSerializer serializer) { + if (_o == null) return null; + switch (_o.Type) { + default: break; + case Value.IntValue: _o.Value_ = serializer.Deserialize(reader); break; + } + return _o; + } +} + +[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] +public enum Other : byte +{ + NONE = 0, + IntValue = 1, +}; + +public class OtherUnion { + public Other Type { get; set; } + public object Value { get; set; } + + public OtherUnion() { + this.Type = Other.NONE; + this.Value = null; + } + + public T As() where T : class { return this.Value as T; } + public union_value_collsion.IntValueT AsIntValue() { return this.As(); } + public static OtherUnion FromIntValue(union_value_collsion.IntValueT _intvalue) { return new OtherUnion{ Type = Other.IntValue, Value = _intvalue }; } + + public static int Pack(Google.FlatBuffers.FlatBufferBuilder builder, OtherUnion _o) { + switch (_o.Type) { + default: return 0; + case Other.IntValue: return union_value_collsion.IntValue.Pack(builder, _o.AsIntValue()).Value; + } + } +} + +public class OtherUnion_JsonConverter : Newtonsoft.Json.JsonConverter { + public override bool CanConvert(System.Type objectType) { + return objectType == typeof(OtherUnion) || objectType == typeof(System.Collections.Generic.List); + } + public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) { + var _olist = value as System.Collections.Generic.List; + if (_olist != null) { + writer.WriteStartArray(); + foreach (var _o in _olist) { this.WriteJson(writer, _o, serializer); } + writer.WriteEndArray(); + } else { + this.WriteJson(writer, value as OtherUnion, serializer); + } + } + public void WriteJson(Newtonsoft.Json.JsonWriter writer, OtherUnion _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; + 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 OtherUnion, serializer); + } + } + public OtherUnion ReadJson(Newtonsoft.Json.JsonReader reader, OtherUnion _o, Newtonsoft.Json.JsonSerializer serializer) { + if (_o == null) return null; + switch (_o.Type) { + default: break; + case Other.IntValue: _o.Value = serializer.Deserialize(reader); break; + } + return _o; + } +} + +public struct IntValue : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_23_1_4(); } + public static IntValue GetRootAsIntValue(ByteBuffer _bb) { return GetRootAsIntValue(_bb, new IntValue()); } + public static IntValue GetRootAsIntValue(ByteBuffer _bb, IntValue obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public IntValue __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public int Value { get { int o = __p.__offset(4); return o != 0 ? __p.bb.GetInt(o + __p.bb_pos) : (int)0; } } + + public static Offset CreateIntValue(FlatBufferBuilder builder, + int value = 0) { + builder.StartTable(1); + IntValue.AddValue(builder, value); + return IntValue.EndIntValue(builder); + } + + public static void StartIntValue(FlatBufferBuilder builder) { builder.StartTable(1); } + public static void AddValue(FlatBufferBuilder builder, int value) { builder.AddInt(0, value, 0); } + public static Offset EndIntValue(FlatBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public IntValueT UnPack() { + var _o = new IntValueT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(IntValueT _o) { + _o.Value = this.Value; + } + public static Offset Pack(FlatBufferBuilder builder, IntValueT _o) { + if (_o == null) return default(Offset); + return CreateIntValue( + builder, + _o.Value); + } +} + +public class IntValueT +{ + [Newtonsoft.Json.JsonProperty("value")] + public int Value { get; set; } + + public IntValueT() { + this.Value = 0; + } +} + +public struct Collision : IFlatbufferObject +{ + private Table __p; + public ByteBuffer ByteBuffer { get { return __p.bb; } } + public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_23_1_4(); } + public static Collision GetRootAsCollision(ByteBuffer _bb) { return GetRootAsCollision(_bb, new Collision()); } + public static Collision GetRootAsCollision(ByteBuffer _bb, Collision obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } + public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); } + public Collision __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public union_value_collsion.Value SomeValueType { get { int o = __p.__offset(4); return o != 0 ? (union_value_collsion.Value)__p.bb.Get(o + __p.bb_pos) : union_value_collsion.Value.NONE; } } + public TTable? SomeValue() where TTable : struct, IFlatbufferObject { int o = __p.__offset(6); return o != 0 ? (TTable?)__p.__union(o + __p.bb_pos) : null; } + public union_value_collsion.IntValue SomeValueAsIntValue() { return SomeValue().Value; } + public union_value_collsion.Other ValueType { get { int o = __p.__offset(8); return o != 0 ? (union_value_collsion.Other)__p.bb.Get(o + __p.bb_pos) : union_value_collsion.Other.NONE; } } + public TTable? Value() where TTable : struct, IFlatbufferObject { int o = __p.__offset(10); return o != 0 ? (TTable?)__p.__union(o + __p.bb_pos) : null; } + public union_value_collsion.IntValue ValueAsIntValue() { return Value().Value; } + + public static Offset CreateCollision(FlatBufferBuilder builder, + union_value_collsion.Value some_value_type = union_value_collsion.Value.NONE, + int some_valueOffset = 0, + union_value_collsion.Other value_type = union_value_collsion.Other.NONE, + int valueOffset = 0) { + builder.StartTable(4); + Collision.AddValue(builder, valueOffset); + Collision.AddSomeValue(builder, some_valueOffset); + Collision.AddValueType(builder, value_type); + Collision.AddSomeValueType(builder, some_value_type); + return Collision.EndCollision(builder); + } + + public static void StartCollision(FlatBufferBuilder builder) { builder.StartTable(4); } + public static void AddSomeValueType(FlatBufferBuilder builder, union_value_collsion.Value someValueType) { builder.AddByte(0, (byte)someValueType, 0); } + public static void AddSomeValue(FlatBufferBuilder builder, int someValueOffset) { builder.AddOffset(1, someValueOffset, 0); } + public static void AddValueType(FlatBufferBuilder builder, union_value_collsion.Other valueType) { builder.AddByte(2, (byte)valueType, 0); } + public static void AddValue(FlatBufferBuilder builder, int valueOffset) { builder.AddOffset(3, valueOffset, 0); } + public static Offset EndCollision(FlatBufferBuilder builder) { + int o = builder.EndTable(); + return new Offset(o); + } + public static void FinishCollisionBuffer(FlatBufferBuilder builder, Offset offset) { builder.Finish(offset.Value); } + public static void FinishSizePrefixedCollisionBuffer(FlatBufferBuilder builder, Offset offset) { builder.FinishSizePrefixed(offset.Value); } + public CollisionT UnPack() { + var _o = new CollisionT(); + this.UnPackTo(_o); + return _o; + } + public void UnPackTo(CollisionT _o) { + _o.SomeValue = new union_value_collsion.ValueUnion(); + _o.SomeValue.Type = this.SomeValueType; + switch (this.SomeValueType) { + default: break; + case union_value_collsion.Value.IntValue: + _o.SomeValue.Value_ = this.SomeValue().HasValue ? this.SomeValue().Value.UnPack() : null; + break; + } + _o.Value = new union_value_collsion.OtherUnion(); + _o.Value.Type = this.ValueType; + switch (this.ValueType) { + default: break; + case union_value_collsion.Other.IntValue: + _o.Value.Value = this.Value().HasValue ? this.Value().Value.UnPack() : null; + break; + } + } + public static Offset Pack(FlatBufferBuilder builder, CollisionT _o) { + if (_o == null) return default(Offset); + var _some_value_type = _o.SomeValue == null ? union_value_collsion.Value.NONE : _o.SomeValue.Type; + var _some_value = _o.SomeValue == null ? 0 : union_value_collsion.ValueUnion.Pack(builder, _o.SomeValue); + var _value_type = _o.Value == null ? union_value_collsion.Other.NONE : _o.Value.Type; + var _value = _o.Value == null ? 0 : union_value_collsion.OtherUnion.Pack(builder, _o.Value); + return CreateCollision( + builder, + _some_value_type, + _some_value, + _value_type, + _value); + } +} + +public class CollisionT +{ + [Newtonsoft.Json.JsonProperty("some_value_type")] + private union_value_collsion.Value SomeValueType { + get { + return this.SomeValue != null ? this.SomeValue.Type : union_value_collsion.Value.NONE; + } + set { + this.SomeValue = new union_value_collsion.ValueUnion(); + this.SomeValue.Type = value; + } + } + [Newtonsoft.Json.JsonProperty("some_value")] + [Newtonsoft.Json.JsonConverter(typeof(union_value_collsion.ValueUnion_JsonConverter))] + public union_value_collsion.ValueUnion SomeValue { get; set; } + [Newtonsoft.Json.JsonProperty("value_type")] + private union_value_collsion.Other ValueType { + get { + return this.Value != null ? this.Value.Type : union_value_collsion.Other.NONE; + } + set { + this.Value = new union_value_collsion.OtherUnion(); + this.Value.Type = value; + } + } + [Newtonsoft.Json.JsonProperty("value")] + [Newtonsoft.Json.JsonConverter(typeof(union_value_collsion.OtherUnion_JsonConverter))] + public union_value_collsion.OtherUnion Value { get; set; } + + public CollisionT() { + this.SomeValue = null; + this.Value = null; + } + + public static CollisionT DeserializeFromJson(string jsonText) { + return Newtonsoft.Json.JsonConvert.DeserializeObject(jsonText); + } + public string SerializeToJson() { + return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented); + } + public static CollisionT DeserializeFromBinary(byte[] fbBuffer) { + return Collision.GetRootAsCollision(new ByteBuffer(fbBuffer)).UnPack(); + } + public byte[] SerializeToBinary() { + var fbb = new FlatBufferBuilder(0x10000); + Collision.FinishCollisionBuffer(fbb, Collision.Pack(fbb, this)); + return fbb.DataBuffer.ToSizedArray(); + } +} + + +}