Skip to content

Commit 87d61ba

Browse files
committed
Support deprecated_readonly in C# json serializer
1 parent 286703e commit 87d61ba

File tree

15 files changed

+316
-13
lines changed

15 files changed

+316
-13
lines changed

src/idl_gen_csharp.cpp

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,21 @@ class CSharpGenerator : public BaseGenerator {
147147
std::string one_file_code;
148148
cur_name_space_ = parser_.current_namespace_;
149149

150+
if (parser_.opts.cs_gen_json_serializer &&
151+
parser_.opts.generate_object_based_api) {
152+
std::string contractresolvercode;
153+
GenJsonContractResolver(&contractresolvercode);
154+
155+
if (parser_.opts.one_file) {
156+
one_file_code += contractresolvercode;
157+
} else {
158+
if (!SaveType("JsonContractResolver", *parser_.current_namespace_,
159+
contractresolvercode, true, parser_.opts)) {
160+
return false;
161+
}
162+
}
163+
}
164+
150165
for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
151166
++it) {
152167
std::string enumcode;
@@ -2395,6 +2410,9 @@ class CSharpGenerator : public BaseGenerator {
23952410
auto utype_name = NamespacedName(*field.value.type.enum_def);
23962411
code +=
23972412
" [Newtonsoft.Json.JsonProperty(\"" + field.name + "_type\")]\n";
2413+
if (field.deprecated == FieldDef::kDeprecatedReadOnly) {
2414+
code += " [JsonReadOnly()]\n";
2415+
}
23982416
if (IsVector(field.value.type)) {
23992417
code += " private " + utype_name + "[] " + camel_name + "Type {\n";
24002418
code += " get {\n";
@@ -2442,6 +2460,8 @@ class CSharpGenerator : public BaseGenerator {
24422460
}
24432461
if (field.attributes.Lookup("hash")) {
24442462
code += " [Newtonsoft.Json.JsonIgnore()]\n";
2463+
} else if (field.deprecated == FieldDef::kDeprecatedReadOnly) {
2464+
code += " [JsonReadOnly()]\n";
24452465
}
24462466
}
24472467
code += " public " + type_name + " " + camel_name + " { get; set; }\n";
@@ -2491,12 +2511,18 @@ class CSharpGenerator : public BaseGenerator {
24912511
code += " public static " + class_name +
24922512
" DeserializeFromJson(string jsonText) {\n";
24932513
code += " return Newtonsoft.Json.JsonConvert.DeserializeObject<" +
2494-
class_name + ">(jsonText);\n";
2514+
class_name +
2515+
">(jsonText, new Newtonsoft.Json.JsonSerializerSettings() {\n";
2516+
code += " ContractResolver = new JsonContractResolver(),\n";
2517+
code += " });\n";
24952518
code += " }\n";
24962519
code += " public string SerializeToJson() {\n";
24972520
code +=
2498-
" return Newtonsoft.Json.JsonConvert.SerializeObject(this, "
2499-
"Newtonsoft.Json.Formatting.Indented);\n";
2521+
" return Newtonsoft.Json.JsonConvert.SerializeObject(this, new "
2522+
"Newtonsoft.Json.JsonSerializerSettings() {\n";
2523+
code += " ContractResolver = new JsonContractResolver(),\n";
2524+
code += " Formatting = Newtonsoft.Json.Formatting.Indented,\n";
2525+
code += " });\n";
25002526
code += " }\n";
25012527
}
25022528
if (parser_.root_struct_def_ == &struct_def) {
@@ -2515,6 +2541,35 @@ class CSharpGenerator : public BaseGenerator {
25152541
code += "}\n\n";
25162542
}
25172543

2544+
void GenJsonContractResolver(std::string *code_ptr) const {
2545+
auto &code = *code_ptr;
2546+
code +=
2547+
"[AttributeUsage(AttributeTargets.Property | "
2548+
"AttributeTargets.Field)]\n";
2549+
code += "class JsonReadOnlyAttribute : Attribute {\n";
2550+
code += "}\n\n";
2551+
2552+
code +=
2553+
"public class JsonContractResolver : "
2554+
"Newtonsoft.Json.Serialization.DefaultContractResolver\n";
2555+
code += "{\n";
2556+
code +=
2557+
" protected override Newtonsoft.Json.Serialization.JsonProperty "
2558+
"CreateProperty(System.Reflection.MemberInfo member, "
2559+
"Newtonsoft.Json.MemberSerialization memberSerialization)\n";
2560+
code += " {\n";
2561+
code +=
2562+
" var property = base.CreateProperty(member, "
2563+
"memberSerialization);\n";
2564+
code +=
2565+
" if (Attribute.IsDefined(member, "
2566+
"typeof(JsonReadOnlyAttribute)))\n";
2567+
code += " property.Readable = false;\n";
2568+
code += " return property;\n";
2569+
code += " }\n";
2570+
code += "}\n\n";
2571+
}
2572+
25182573
// This tracks the current namespace used to determine if a type need to be
25192574
// prefixed by its namespace
25202575
const Namespace *cur_name_space_;
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// <auto-generated>
2+
// automatically generated by the FlatBuffers compiler, do not modify
3+
// </auto-generated>
4+
5+
namespace KeywordTest
6+
{
7+
8+
using global::System;
9+
using global::System.Collections.Generic;
10+
using global::Google.FlatBuffers;
11+
12+
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
13+
class JsonReadOnlyAttribute : Attribute {
14+
}
15+
16+
public class JsonContractResolver : Newtonsoft.Json.Serialization.DefaultContractResolver
17+
{
18+
protected override Newtonsoft.Json.Serialization.JsonProperty CreateProperty(System.Reflection.MemberInfo member, Newtonsoft.Json.MemberSerialization memberSerialization)
19+
{
20+
var property = base.CreateProperty(member, memberSerialization);
21+
if (Attribute.IsDefined(member, typeof(JsonReadOnlyAttribute)))
22+
property.Readable = false;
23+
return property;
24+
}
25+
}
26+
27+
28+
}

tests/MyGame/Example/ArrayTable.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,15 @@ public ArrayTableT() {
5757
}
5858

5959
public static ArrayTableT DeserializeFromJson(string jsonText) {
60-
return Newtonsoft.Json.JsonConvert.DeserializeObject<ArrayTableT>(jsonText);
60+
return Newtonsoft.Json.JsonConvert.DeserializeObject<ArrayTableT>(jsonText, new Newtonsoft.Json.JsonSerializerSettings() {
61+
ContractResolver = new JsonContractResolver(),
62+
});
6163
}
6264
public string SerializeToJson() {
63-
return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented);
65+
return Newtonsoft.Json.JsonConvert.SerializeObject(this, new Newtonsoft.Json.JsonSerializerSettings() {
66+
ContractResolver = new JsonContractResolver(),
67+
Formatting = Newtonsoft.Json.Formatting.Indented,
68+
});
6469
}
6570
public static ArrayTableT DeserializeFromBinary(byte[] fbBuffer) {
6671
return ArrayTable.GetRootAsArrayTable(new ByteBuffer(fbBuffer)).UnPack();
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// <auto-generated>
2+
// automatically generated by the FlatBuffers compiler, do not modify
3+
// </auto-generated>
4+
5+
namespace MyGame.Example
6+
{
7+
8+
using global::System;
9+
using global::System.Collections.Generic;
10+
using global::Google.FlatBuffers;
11+
12+
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
13+
class JsonReadOnlyAttribute : Attribute {
14+
}
15+
16+
public class JsonContractResolver : Newtonsoft.Json.Serialization.DefaultContractResolver
17+
{
18+
protected override Newtonsoft.Json.Serialization.JsonProperty CreateProperty(System.Reflection.MemberInfo member, Newtonsoft.Json.MemberSerialization memberSerialization)
19+
{
20+
var property = base.CreateProperty(member, memberSerialization);
21+
if (Attribute.IsDefined(member, typeof(JsonReadOnlyAttribute)))
22+
property.Readable = false;
23+
return property;
24+
}
25+
}
26+
27+
28+
}

tests/MyGame/Example/Monster.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1085,10 +1085,15 @@ public MonsterT() {
10851085
}
10861086

10871087
public static MonsterT DeserializeFromJson(string jsonText) {
1088-
return Newtonsoft.Json.JsonConvert.DeserializeObject<MonsterT>(jsonText);
1088+
return Newtonsoft.Json.JsonConvert.DeserializeObject<MonsterT>(jsonText, new Newtonsoft.Json.JsonSerializerSettings() {
1089+
ContractResolver = new JsonContractResolver(),
1090+
});
10891091
}
10901092
public string SerializeToJson() {
1091-
return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented);
1093+
return Newtonsoft.Json.JsonConvert.SerializeObject(this, new Newtonsoft.Json.JsonSerializerSettings() {
1094+
ContractResolver = new JsonContractResolver(),
1095+
Formatting = Newtonsoft.Json.Formatting.Indented,
1096+
});
10921097
}
10931098
public static MonsterT DeserializeFromBinary(byte[] fbBuffer) {
10941099
return Monster.GetRootAsMonster(new ByteBuffer(fbBuffer)).UnPack();
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// <auto-generated>
2+
// automatically generated by the FlatBuffers compiler, do not modify
3+
// </auto-generated>
4+
5+
namespace MyGame
6+
{
7+
8+
using global::System;
9+
using global::System.Collections.Generic;
10+
using global::Google.FlatBuffers;
11+
12+
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
13+
class JsonReadOnlyAttribute : Attribute {
14+
}
15+
16+
public class JsonContractResolver : Newtonsoft.Json.Serialization.DefaultContractResolver
17+
{
18+
protected override Newtonsoft.Json.Serialization.JsonProperty CreateProperty(System.Reflection.MemberInfo member, Newtonsoft.Json.MemberSerialization memberSerialization)
19+
{
20+
var property = base.CreateProperty(member, memberSerialization);
21+
if (Attribute.IsDefined(member, typeof(JsonReadOnlyAttribute)))
22+
property.Readable = false;
23+
return property;
24+
}
25+
}
26+
27+
28+
}

tests/MyGame/MonsterExtra.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,10 +191,15 @@ public MonsterExtraT() {
191191
}
192192

193193
public static MonsterExtraT DeserializeFromJson(string jsonText) {
194-
return Newtonsoft.Json.JsonConvert.DeserializeObject<MonsterExtraT>(jsonText);
194+
return Newtonsoft.Json.JsonConvert.DeserializeObject<MonsterExtraT>(jsonText, new Newtonsoft.Json.JsonSerializerSettings() {
195+
ContractResolver = new JsonContractResolver(),
196+
});
195197
}
196198
public string SerializeToJson() {
197-
return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented);
199+
return Newtonsoft.Json.JsonConvert.SerializeObject(this, new Newtonsoft.Json.JsonSerializerSettings() {
200+
ContractResolver = new JsonContractResolver(),
201+
Formatting = Newtonsoft.Json.Formatting.Indented,
202+
});
198203
}
199204
public static MonsterExtraT DeserializeFromBinary(byte[] fbBuffer) {
200205
return MonsterExtra.GetRootAsMonsterExtra(new ByteBuffer(fbBuffer)).UnPack();
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// <auto-generated>
2+
// automatically generated by the FlatBuffers compiler, do not modify
3+
// </auto-generated>
4+
5+
namespace NamespaceA
6+
{
7+
8+
using global::System;
9+
using global::System.Collections.Generic;
10+
using global::Google.FlatBuffers;
11+
12+
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
13+
class JsonReadOnlyAttribute : Attribute {
14+
}
15+
16+
public class JsonContractResolver : Newtonsoft.Json.Serialization.DefaultContractResolver
17+
{
18+
protected override Newtonsoft.Json.Serialization.JsonProperty CreateProperty(System.Reflection.MemberInfo member, Newtonsoft.Json.MemberSerialization memberSerialization)
19+
{
20+
var property = base.CreateProperty(member, memberSerialization);
21+
if (Attribute.IsDefined(member, typeof(JsonReadOnlyAttribute)))
22+
property.Readable = false;
23+
return property;
24+
}
25+
}
26+
27+
28+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// <auto-generated>
2+
// automatically generated by the FlatBuffers compiler, do not modify
3+
// </auto-generated>
4+
5+
namespace NamespaceA.NamespaceB
6+
{
7+
8+
using global::System;
9+
using global::System.Collections.Generic;
10+
using global::Google.FlatBuffers;
11+
12+
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
13+
class JsonReadOnlyAttribute : Attribute {
14+
}
15+
16+
public class JsonContractResolver : Newtonsoft.Json.Serialization.DefaultContractResolver
17+
{
18+
protected override Newtonsoft.Json.Serialization.JsonProperty CreateProperty(System.Reflection.MemberInfo member, Newtonsoft.Json.MemberSerialization memberSerialization)
19+
{
20+
var property = base.CreateProperty(member, memberSerialization);
21+
if (Attribute.IsDefined(member, typeof(JsonReadOnlyAttribute)))
22+
property.Readable = false;
23+
return property;
24+
}
25+
}
26+
27+
28+
}

tests/nested_namespace_test/nested_namespace_test1_generated.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,21 @@ namespace NamespaceB
99
using global::System.Collections.Generic;
1010
using global::Google.FlatBuffers;
1111

12+
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
13+
class JsonReadOnlyAttribute : Attribute {
14+
}
15+
16+
public class JsonContractResolver : Newtonsoft.Json.Serialization.DefaultContractResolver
17+
{
18+
protected override Newtonsoft.Json.Serialization.JsonProperty CreateProperty(System.Reflection.MemberInfo member, Newtonsoft.Json.MemberSerialization memberSerialization)
19+
{
20+
var property = base.CreateProperty(member, memberSerialization);
21+
if (Attribute.IsDefined(member, typeof(JsonReadOnlyAttribute)))
22+
property.Readable = false;
23+
return property;
24+
}
25+
}
26+
1227
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))]
1328
public enum Color : sbyte
1429
{

0 commit comments

Comments
 (0)