使用155-questions-active
查询Stack Overflow websockets我得到以下内容(格式不正确)JSON:
{
"action":"155-questions-active",
"data":
"{
\"siteBaseHostAddress\":\"stackoverflow.com\",
\"id\":23747905,
\"titleEncodedFancy\":\"Load sqlite extension in Django\",
\"bodySummary\":\"I have built a sqlite <snip>\",
\"tags\":[\"django\",\"sqlite\",\"pysqlite\"],
\"lastActivityDate\":1400544795,
\"url\":\"http://stackoverflow.com/questions/23747905/<snip>\",
\"ownerUrl\":\"http://stackoverflow.com/users/1311165/pro-chats\",
\"ownerDisplayName\":\"Pro Chats\",
\"apiSiteParameter\":\"stackoverflow\"
}"
}
应用一些修正后
private string MakeJsonCapable(string input)
{
input = input.Trim();
input = input.Replace("data\":\"", "data\":");
input = input.Remove(input.LastIndexOf("\""), 1);
input = input.Replace("\\", string.Empty);
return input;
}
我得到了这个结果:
{
"action": "155-questions-active",
"data": {
"siteBaseHostAddress": "stackoverflow.com",
"id": 23747905,
"titleEncodedFancy": "Load sqlite extension in Django",
"bodySummary": "I have built a sqlite <snip>",
"tags": [
"django",
"sqlite",
"pysqlite"
],
"lastActivityDate": 1400544795,
"url": "http:\/\/stackoverflow.com\/questions\/23747905\/<snip>",
"ownerUrl": "http:\/\/stackoverflow.com\/users\/1311165\/pro-chats",
"ownerDisplayName": "Pro Chats",
"apiSiteParameter": "stackoverflow"
}
}
现在可接受的JSON(我正在使用some online JSON format tool验证这一点)由JSON.NET完美解析。
当一个值(到目前为止我只在bodySummary
中看到但我怀疑titleEncodedFancy
也可能有这个)包含"
时,会出现问题。在使其成为Json-able之前传递的字面值是\\\"Compliant Solution\\\"
:3个反斜杠和一个重音。
请注意,这是文字值,并且不包含调试器的任何反斜杠:这是直接从textview获取的; watch变量显示7个反斜杠。
显然这是一个问题,因为现在我的bodySummary
包含一个未转义的"
,它会破坏反序列化。出于这个原因,我无法创建自定义JsonConverter
来自己逃避它们,因为它不会在第一时间获得正确的值。
如何删除出现在重音符号前面的不需要的反斜杠,表示字段名称及其值的开头和结尾?
或者:也许我首先错误地解析data
字段。如果是这样的话:正确的方法是什么?
答案 0 :(得分:2)
这里有的是已经序列化为字符串,放在另一个对象中然后第二次序列化的数据。要正确地恢复所有内容,您可以撤消该过程。定义两个类,一个用于外部序列化,另一个用于内部:
class Outer
{
public string Action { get; set; }
public string Data { get; set; }
}
class Inner
{
public string SiteBaseHostAddress { get; set; }
public int Id { get; set; }
public string TitleEncodedFancy { get; set; }
public string BodySummary { get; set; }
public string[] Tags { get; set; }
public int LastActivityDate { get; set; }
public string Url { get; set; }
public string OwnerUrl { get; set; }
public string OwnerDisplayName { get; set; }
public string ApiSiteParameter { get; set; }
}
然后像这样反序列化:
Outer outer = JsonConvert.DeserializeObject<Outer>(json);
Inner inner = JsonConvert.DeserializeObject<Inner>(outer.Data);
执行此操作时,请勿对输入字符串应用“修复”。让JSON解析器完成它的工作。
修改强>
如果要保持父子关系,则需要自定义JsonConverter
来处理子对象的反序列化。为此,首先需要将外部类的定义更改为:
class Outer
{
public string Action { get; set; }
[JsonConverter(typeof(InnerConverter))]
public Inner Data { get; set; }
}
像这样创建InnerConverter
类:
class InnerConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(Inner));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JToken token = JToken.Load(reader);
return JsonConvert.DeserializeObject<Inner>(token.ToString());
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
最后,您可以像这样反序列化:
Outer outer = JsonConvert.DeserializeObject<Outer>(json);
答案 1 :(得分:1)
按照Brian Rogers的建议,我创建了一个简单的转换器来处理它:
public sealed class Response
{
[JsonProperty("action")]
public string Action { get; internal set; }
[JsonProperty("data")]
[JsonConverter(typeof (DataConverter))]
public Data Data { get; internal set; }
}
public sealed class Data
{
[JsonProperty("siteBaseHostAddress")]
public string SiteBaseHostAddress { get; internal set; }
[JsonProperty("id")]
public string Id { get; internal set; }
[JsonProperty("titleEncodedFancy")]
public string TitleEncodedFancy { get; internal set; }
[JsonProperty("bodySummary")]
public string BodySummary { get; internal set; }
[JsonProperty("tags")]
public IEnumerable<string> Tags { get; internal set; }
[JsonProperty("lastActivityDate")]
[JsonConverter(typeof (EpochTimeConverter))]
public DateTime LastActivityDate { get; internal set; }
[JsonProperty("url")]
[JsonConverter(typeof (UriConverter))]
public Uri QuestionUrl { get; internal set; }
[JsonProperty("ownerUrl")]
[JsonConverter(typeof (UriConverter))]
public Uri OwnerUrl { get; internal set; }
[JsonProperty("ownerDisplayName")]
public string OwnerDisplayName { get; internal set; }
[JsonProperty("apiSiteParameter")]
public string ApiSiteParameter { get; internal set; }
}
internal sealed class DataConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof (string);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue,
JsonSerializer serializer)
{
var value = reader.Value as string;
return JsonConvert.DeserializeObject<Data>(value);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
现在我可以用
完全反序列化它var responseObject = JsonConvert.DeserializeObject<Response>(result);