Reputation: 6855
So my json data is coming as string like following:
{ "name":"aaa", "sub": "{"x":"sss", "y":"eee"}" }
Sub field is a raw json string here.
My model is like following.
class Main
{
public string Name { get;set;}
public Sub Sub { get;set;}
}
class Sub
{
public string X { get;set;}
public string Y { get;set;}
}
I want to deserialize it like following:
var response = Encoding.UTF8.GetString(bytes); // getting data.
var jsonString = JsonConvert.Deseialize(response).ToString(); // to string.
var model = JsonConvert.Deserialize<Main>(jsonString); // error
The last step throws exception, like "string can not cast to Main" class.
Upvotes: 1
Views: 891
Reputation: 18155
As mentioned in other Answers, you need a 2-Step deserialization.However, if you do not want to introduce a Custom JsonConverter, you could introduce a new property in the Main class which could assist in deserialization. For example,
class Main
{
public string Name { get;set;}
private string _subString;
[JsonProperty("Sub")]
public string SubString {
get => _subString;
set
{
_subString = value;
Sub = JsonConvert.DeserializeObject<Sub>(_subString);
}
}
[JsonIgnore]
public Sub Sub { get;set;}
}
class Sub
{
public string X { get;set;}
public string Y { get;set;}
}
The Sub
property would not be assigned during initial deserializing (step 1), instead, when the SubString
property is assigned, it would make another call to Deserialize the string value and assign the Sub
property.
Upvotes: 1
Reputation: 118937
Assuming your question has a typo and you meant to escape the double quotes, e.g.:
{ "name":"aaa", "sub": "{\"x\":\"sss\", \"y\":\"eee\"}" }
Then you can achieve this with a custom converter. For example:
public class NestedJsonConverter : JsonConverter
{
public override bool CanConvert(Type objectType) => true;
public override object? ReadJson(JsonReader reader, Type objectType,
object? existingValue, JsonSerializer serializer)
{
// Get the raw string
var s = serializer.Deserialize<string>(reader);
// Deserialise into the correct type
return JsonConvert.DeserializeObject(s, objectType);
}
public override void WriteJson(JsonWriter writer, object? value,
JsonSerializer serializer)
=> throw new NotImplementedException();
}
And change your model to add the attribute:
class Main
{
public string Name { get; set; }
[JsonConverter(typeof(NestedJsonConverter))]
public Sub Sub { get; set; }
}
Now you can simply deserialise like this:
var result = JsonConvert.DeserializeObject<Main>(jsonString);
Upvotes: 2
Reputation: 218828
It sounds like you need a 2-step deserialization. If the value of sub
is a string then it's a string, not a Sub
instance. That string may be a JSON representation of a Sub
instance, but that's another deserialization altogether.
First deserialize into the type represented by the whole object:
class Main
{
public string Name { get;set; }
public string Sub { get;set; }
}
and:
var mainObj = JsonConvert.DeserializeObject<Main>(response);
Then mainObj.Sub
would contain the JSON string for your next type:
class Sub
{
public string X { get;set; }
public string Y { get;set; }
}
Which you can deserialize the same way:
var subObj = JsonConvert.DeserializeObject<Sub>(mainObj.Sub);
Overall the process of deserializing a JSON string to an object is the same. You just have to do it twice when you have two JSON strings.
Upvotes: 0