如何反序列化原始json字段模型使用Newtonsoft?



那么我的json数据将以字符串形式出现,如下所示:

{ "name":"aaa", "sub": "{"x":"sss", "y":"eee"}" }

子字段是一个原始json字符串。

我的模型是这样的。

class Main
{
public string Name { get;set;}
public Sub Sub { get;set;}
}
class Sub
{
public string X { get;set;}
public string Y { get;set;}
}

我想像这样反序列化它:

var response = Encoding.UTF8.GetString(bytes); // getting data.
var jsonString = JsonConvert.Deseialize(response).ToString(); // to string.
var model = JsonConvert.Deserialize<Main>(jsonString); // error

最后一步抛出异常,如"string can not cast to main";类。

假设你的问题有拼写错误,你想要转义双引号,例如:

{ "name":"aaa", "sub": "{"x":"sss", "y":"eee"}" }

然后您可以使用自定义转换器实现这一点。例如:

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();
}

并更改模型以添加属性:

class Main
{
public string Name { get; set; }

[JsonConverter(typeof(NestedJsonConverter))]
public Sub Sub { get; set; }
}

现在你可以像这样简单地反序列化:

var result = JsonConvert.DeserializeObject<Main>(jsonString);

如其他回答中所述,您需要两步反序列化。然而,如果你不想引入自定义JsonConverter,你可以在Main类中引入一个新的属性,它可以帮助反序列化。例如,

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;}
}

在初始反序列化(步骤1)期间不分配Sub属性,相反,当分配SubString属性时,它将再次调用反序列化字符串值并分配Sub属性。

听起来您需要两步反序列化。如果sub的值是字符串,那么它就是字符串,而不是Sub实例。该字符串可能是Sub实例的JSON表示,但这完全是另一种反序列化。

首先反序列化为整个对象所表示的类型:

class Main
{
public string Name { get;set; }
public string Sub { get;set; }
}

:

var mainObj = JsonConvert.DeserializeObject<Main>(response);

那么mainObj.Sub将包含您的下一个类型的JSON字符串:

class Sub
{
public string X { get;set; }
public string Y { get;set; }
}

可以用同样的方式反序列化:

var subObj = JsonConvert.DeserializeObject<Sub>(mainObj.Sub);

总的来说,将JSON字符串反序列化为对象的过程是相同的。当你有两个JSON字符串时,你只需要做两次。