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
- use Regex to make it a real JSON
- 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"
}
}