使用NewtonSoft反序列化JSON时无法将字符串转换为对象
解决NewtonSoft反序列化时字符串转对象的问题
看你给出的JSON数据,问题核心出在user字段上——它的值是一个带转义符的JSON字符串(比如包含\r\n和转义双引号),而非直接的JSON对象。默认情况下NewtonSoft会把它当成普通字符串处理,但你应该是想把它解析成对应的User实体,所以才会触发转换错误。
下面给你几种可行的解决办法:
方法1:修改JSON源(最直接,若能控制源头)
如果可以调整生成这个JSON的上游服务,把user字段的外层引号和转义符去掉,让它直接成为一个JSON对象:
原JSON的
user片段:"user":"{\r\n \"Active\": true,\r\n \"DisplayName\": \"Sakib Hasan\",...}"
修改后:"user":{\r\n "Active": true,\r\n "DisplayName": "Sakib Hasan",...}
这样直接用常规的类结构反序列化就不会有问题了。
方法2:分两步反序列化(无需修改JSON)
如果没法改动JSON源,我们可以先把user当成字符串接收,再单独解析这个字符串为User对象:
步骤1:定义临时接收类和目标User类
// 临时类:用来接收第一次反序列化的结果,user字段设为string类型 public class TempTokenResponse { public string access_token { get; set; } public string token_type { get; set; } public int expires_in { get; set; } public string refresh_token { get; set; } // 带点的字段需要用JsonProperty映射C#属性名 [JsonProperty(".issued")] public string Issued { get; set; } [JsonProperty(".expires")] public string Expires { get; set; } public string ip_address { get; set; } public string client_id { get; set; } public string user { get; set; } } // 你的User实体类 public class User { public bool Active { get; set; } public string DisplayName { get; set; } public string Email { get; set; } public bool EmailVarified { get; set; } public string Language { get; set; } public string PhoneNumber { get; set; } public string ProfileImageUrl { get; set; } public List<string> Roles { get; set; } }
步骤2:执行两次反序列化
// 第一步:把整个JSON反序列化成临时类 var tempResult = JsonConvert.DeserializeObject<TempTokenResponse>(yourJsonString); // 第二步:把user字符串单独解析成User对象 var user = JsonConvert.DeserializeObject<User>(tempResult.user); // 后续可将user赋值给最终的响应类对象,或直接使用
方法3:自定义JsonConverter(一键自动处理)
如果你想一步完成反序列化,可以自定义转换器,让NewtonSoft自动把user的字符串解析成对象:
步骤1:实现自定义转换器
public class StringToObjectConverter<T> : JsonConverter<T> { public override T ReadJson(JsonReader reader, Type objectType, T existingValue, bool hasExistingValue, JsonSerializer serializer) { // 若读取到的是字符串,就将其反序列化为目标类型 if (reader.TokenType == JsonToken.String) { var jsonStr = reader.Value.ToString(); return JsonConvert.DeserializeObject<T>(jsonStr); } // 否则按常规逻辑处理 return serializer.Deserialize<T>(reader); } public override void WriteJson(JsonWriter writer, T value, JsonSerializer serializer) { // 若需要序列化回去,可在此将对象转为字符串 var jsonStr = JsonConvert.SerializeObject(value); writer.WriteValue(jsonStr); } }
步骤2:在目标类的user属性上应用转换器
public class TokenResponse { public string access_token { get; set; } public string token_type { get; set; } public int expires_in { get; set; } public string refresh_token { get; set; } [JsonProperty(".issued")] public string Issued { get; set; } [JsonProperty(".expires")] public string Expires { get; set; } public string ip_address { get; set; } public string client_id { get; set; } // 给user属性绑定自定义转换器 [JsonConverter(typeof(StringToObjectConverter<User>))] public User user { get; set; } } // User类同方法2定义 public class User { public bool Active { get; set; } public string DisplayName { get; set; } public string Email { get; set; } public bool EmailVarified { get; set; } public string Language { get; set; } public string PhoneNumber { get; set; } public string ProfileImageUrl { get; set; } public List<string> Roles { get; set; } }
步骤3:直接反序列化
var response = JsonConvert.DeserializeObject<TokenResponse>(yourJsonString); // 此时response.user已经是解析完成的User对象
另外注意:你提供的JSON中Roles数组是截断状态([\r\n \"anonymous\",\r...}),实际使用时要确保JSON完整,否则也会导致反序列化失败哦。
内容的提问来源于stack exchange,提问作者SZT
相关产品推荐
相关产品推荐

