Home > Enterprise >  How to convert a json within a json into object?
How to convert a json within a json into object?

Time:09-01

So I got this guy

{
  "lng_x": "106.883368",
  "style": "{\"name\":\"TACTICAL\"}"
}

Which I wanted to make into this guy

public class Root
{
    public string lng_x { get; set; }
    public Style style { get; set; }
}

public class Style
{
    public string name { get; set; }
}

But I got this instead

public class Root
{
    public string lng_x { get; set; }
    public string style { get; set; }
}

I know that the Json is supposed to be like this

{
  "lng_x": "106.883368",
  "style": 
  {
    "name": "TACTICAL"
  }
}

But I can't because it is already like that when I got it.

Is there any way so that I don't have to deserialize it again?

CodePudding user response:

If you can't fix the JSON document you can create a custom JSON type converter and apply it to the style property. And whoever created that document needs to fix their bug.

If you use System.Text.Json, a possible converter could be :

public class StyleStringJsonConverter : JsonConverter<Style>
{
    public override Style Read(
        ref Utf8JsonReader reader,
        Type typeToConvert,
        JsonSerializerOptions options) =>
            JsonSerializer.Deserialize<Style>(reader.GetString()!);

    public override void Write(
        Utf8JsonWriter writer,
        Style style,
        JsonSerializerOptions options) =>
            writer.WriteStringValue(JsonSerializer.Serialize(style));
}

This can be applied through an attribute :

public class Root
{
    public string lng_x { get; set; }
    [JsonConverter(typeof(StyleStringJsonConverter))]
    public Style style { get; set; }
}

JSON.NET also has custom converters:

public class StyleStringConverter : JsonConverter<Style>
{
    public override void WriteJson(JsonWriter writer, Style value, JsonSerializer serializer)
    {
        writer.WriteValue(JsonConvert.SerializeObject(value));
    }

    public override Style ReadJson(JsonReader reader, Type objectType, Style existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        string s = (string)reader.Value;

        return JsonConvert.DeserializeObject<Style>(s);
    }

}

This can be applied using an attribute too:

public class Root
{
    public string lng_x { get; set; }
    [JsonConverter(typeof(StyleStringJsonConverter))]
    public Style style { get; set; }
}

CodePudding user response:

As stated before, the original creators should fix your the JSON file. Meanwhile, you are stuck with it.

To make sure you don't dirty your own code

  1. use Regex to make it a real JSON
  2. Deserialize as normal

Advantage: When the JSON is changed to a correct form you have to remove the CleanJSON Method and your code will stay working.

The Code

using System.Text.Json;
using System.Text.RegularExpressions;

function YourFunction(){
    //-- Get your JSON in string format (from API, file,...)
    string _jsonString = ... ;
    CleanJSON(_jsonString);
    YourModels.Root _correctStructure = (JsonSerializer.Deserialize<YourModels.Root>(_JSsonString);
}

function CleanJSON(string jsonString){
    //__ Probably you can group the regex
    string _regexPatternRoot = @"(\\"")(.*?)(\\)";
    string _regexReplacementRoot = @"""$2";
    string _regexPatternStyle = "\"({)\"(.*?)\"}\"";
    string _regexReplacementStyle = @"$1""$2""}";

    _JSsonString = Regex.Replace(_JSsonString, _regexPatternRoot, _regexReplacementRoot);
    _JSsonString = Regex.Replace(_JSsonString, _regexPatternStyle, _regexReplacementStyle);
}

CodePudding user response:

you don't need any custom converter. The problem is that your origional style property is a json string and you have to deserialize it. In this case I usually use a JsonConstructor

public class Root
{
    public string lng_x { get; set; }
    public Style style { get; set; }
    
    [JsonConstructor]
    public Root (string style)
    {
        this.style=JsonConvert.DeserializeObject<Style>(style);
    }
    public Root (){}
}

test

Root data = JsonConvert.DeserializeObject<Root>(json);

{
  "lng_x": "106.883368",
  "style": {
    "name": "TACTICAL"
  }
}
  • Related