How to serialize "union-like" field in C # using Json.NET

I am trying to create a JSON file that will be used as part of the Dojo framework and would like to return the position attribute that will be used in dojo.place() . The position parameter can be either a number or a string.

Using StructLayout doesn't seem to work as it is, since the serializer will try to emit both String and Integer types. I am looking at creating a custom ContractResolver that overrides CreatePrimitiveContract to return a custom JsonConverter . However, looking at the API, it seems that the JsonConverter is created based on the type and not the specific value of the object.

How can I handle this case in C # using the Json.NET serializer?

Presumably, the solution will include two properties with custom installers to discard another property when it is installed with some ordinary Json.Net class to check property values ​​and only serialize nonzero.

** Hypothetical example **

 // C# struct (or class) [StructLayout(LayoutKind.Explicit)] struct DojoPosition { [JsonProperty(PropertyName="position")] [FieldOffset(0)] public String StrPos; [JsonProperty(PropertyName="position")] [FieldOffset(0)] public Int32 IntPos; } // Serialization output DojoPosition pos; pos.StrPos = "only"; var output = JsonConvert.SerializeObject(pos); // Output is: { "position": "only" } pos.IntPos = 3; var output = JsonConvert.SerializeObject(pos); // Output is: { "position": 3 } 
+4
source share
1 answer

I just had a similar problem. For simple contract manipulation see: Redefining Serialization Behavior in Json.Net

To enable JsonPrimitiveContract, override the CreateContract method.

Here is an example based on our solution:

  public class JsonDotNetContractResolver : DefaultContractResolver { protected override JsonContract CreateContract(Type objectType) { if (typeof(DojoPosition).IsAssignableFrom(objectType)) { return new JsonPrimitiveContract(objectType.GetGenericArguments()[1]) { CreatedType = typeof(object), // Not sure this will work for you, or is necessary... IsReference = false, Converter = DojoPositionConverter, }; } return base.CreateContract(objectType); } private class DojoPositionConverter : JsonConverter { public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { var dp = (DojoPosition) value; if(string.IsNullOrEmpty(dp.StrPos)) serializer.Serialize(writer,dp.IntPos); else serializer.Serialize(writer,dp.StrPos); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { //... } public override bool CanConvert(Type objectType) { //.... } } } 

How to determine the type of deserialization from the reader is homework;)

+1
source

Source: https://habr.com/ru/post/1381162/


All Articles