Home > Mobile >  How to inline JSON structure with System.Text.Json
How to inline JSON structure with System.Text.Json

Time:09-06

I am looking for the equivalent of Golang's json: "inline" tag with C#'s System.Text.Json.

For example, I have the following class structure in C#:

class Outer{
    public string Hello;
    public Inner TheInner;
}

class Inner{
    public string World;
}

And I want the serialized and deserialized JSON text to be

{
   "Hello" : "example_value_01",
   "World" : "example_value_02"
}

In Golang, I can achieve this with the following structure definition


type Outer struct{
    Hello string
    TheInner Inner `json: "inline"`
}

type Inner struct{
   World string
}

However, I cannot find a decent way to do this in C#'s System.Text.Json.

CodePudding user response:

There's not really any built-in functionality to do that in C#. However, you can write your own JSON converter like this:

public class InnerConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        Inner inner = (Inner)value;

        writer.WriteValue(inner.World);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        Inner inner = new Inner();
        inner.World = (string)reader.Value;

        return inner;
    }

    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(Inner);
    }
}

[JsonConverter(typeof(InnerConverter))]
public class Inner
{
    public string World { get; set; }
}

This won't quite get you where you want, however, because the resulting JSON will look like this:

{
   "Hello" : "example_value_01",
   "TheInner" : "example_value_02"
}

So, you'll also have to modify Outer:

public class Outer{

    public string Hello { get; set; }

    [JsonProperty("World")]
    public Inner TheInner { get; set; }
}

This will give you the output you're looking for.

CodePudding user response:

To reach it in c# , you don't need any custom classes at all,you can use a dictionary

var dict = new Dictionary<string, string> {
                           {"Hello","example1"},
                           {"World","example2"}
                           };
                           
var json= System.Text.Json.JsonSerializer.Serialize(dict,new JsonSerializerOptions { WriteIndented = true});    

result

{
  "Hello": "example1",
  "World": "example2"
}

but if you want it a hard way it is much easier to make it using Newtonsoft.Json since Text.Json needs a custom serializer for almost everything

using Newtonsoft.Json;

    var json = SerializeOuterObj(obj, "TheInner");


public string SerializeOuterObj(object outerObj, string innerObjectPropertyName)
{
    var jsonParsed = JObject.FromObject(outerObj);
    var prop = jsonParsed.Properties().Where(i => i.Name == innerObjectPropertyName).First();
    prop.Remove();
    foreach (var p in ((JObject)prop.Value).Properties())
        jsonParsed.Add(p.Name, p.Value);
    return jsonParsed.ToString();
}
  • Related