I have some JSON data, which I wish to deserialize into a C# object.
The data looks like this:
{
"version": 0,
"guid": "2166a7d5744d47009adaa29f0e549696",
"csv": "one:1,two:2,three:3",
"method": "substract"
}
The "csv" property is giving me trouble, as I want it to be deserialized to the following csv object (it's content can change, so it can have more or less comma-separated values):
public class CSV
{
public int One {get;set;}
public bool Two {get;set;}
public int Three {get;set;}
}
I already have an object for the bigger JSON:
public class MyJsonData
{
public int Version {get;set;}
public string Guid {get;set;}
public string Csv {get;set;}
public string Method {get;set;}
}
But I just can't figure out how to parse the comma-separated string to my CSV object.
I tried adding a public CSV (string s)
constructor to the CSV object and changing the type from string
to CSV
in the MyJsonData
object, hoping C# would use that constructor (I'm using System.Text.Json
) but it didn't and it threw an exception.
The only thing I can come up is separating the string by commas and using reflection to fill the CSV object properties (I've defined all possible values the string can have and expect the missing ones to be empty or have the default value for the type). But I'm looking for a more elegant solution, as I am accessing the MyJsonData
object everywhere in my code, so having to separately handle a CSV
object seems cumbersome and a worst-practice.
Is there any way to tell JSON what method to use to convert the string to my CSV
object when deserializing?
CodePudding user response:
If you use Newtonsoft.Json you will need only one more string of code
using Newtonsoft.Json;
MyJsonData myJsonData = JsonConvert.DeserializeObject<MyJsonData>(json);
public class MyJsonData
{
public CSV Csv { get; set; }
//...another properties
[JsonConstructor]
public MyJsonData(string csv)
{
Csv = new JObject(csv.Split(",")
.Select(i => i.Split(":"))
.Select(r => new JProperty(r[0].ToString(), Convert.ToInt32(r[1]))))
.ToObject<CSV>();
}
}
If you use Text.Json with Net 6 , the shortest code probably is
var jDoc = JsonNode.Parse(json);
jDoc["csv"] = new JsonObject( JsonDocument.Parse(json).RootElement
.GetProperty("csv").GetString()
.Split(",")
.Select(r => r.Split(":") )
.Select(i=> KeyValuePair.Create<string, JsonNode>(i[0], Convert.ToInt32(i[1]))));
MyJsonData myJsonData = jDoc.Deserialize<MyJsonData>( new JsonSerializerOptions {PropertyNameCaseInsensitive = true});
if you want one line of code you will probably wrap this code in a custom formater ( as it is usually in the most cases when you use Text.Json)
UPDATE
if some of CSV properties are boolean, you can try this code
Csv = new JObject(csv.Split(",")
.Select(i => i.Split(":"))
.Select(r => new JProperty(r[0].ToString(),
r[1].ToLower() =="true"||r[1].ToLower() =="false"? Convert.ToBoolean( r[1]):
Convert.ToInt32(r[1]))))
.ToObject<CSV>();