如何安全地将包含转义JSON的字符串转换为有效的JSON?

23

我正在与第三方API进行通信,该API返回JSON响应如下:

"{\"SomeResponse\":{\"FIrstAttribute\":8,\"SecondAttribute\":\"On\",\"ThirdAttribute\":{\"Id\":2,\"FirstName\":\"Okkie\",\"Name\":\"Bokkie\",\"Street\":\"\",\"StreetNumber\":null,\"PostCode\":\"\",\"City\":\"\",\"Country\":\"}}}"

这有点像JSON...但是作为字符串。请注意第一和最后的双引号以及所有转义斜杠。

目前,我通过使用String.replace解决这个问题,替换反斜杠和第一个和最后一个引号。之后,我就可以解析它了。

mystring.Replace("\\", "");

然而,如果其中一个属性实际上具有反斜杠作为值,该怎么办?例如:

\"SecondAttribute\":\"My Super Back Slash: \\ . That was it.\"

如果那样的话,我会意外地删除值中应该存在的反斜杠。

有人有关于如何正确解析这个 JSON 字符串的好主意吗?


4
你发布的版本中,你是如何看到它的?它是否实际包含所有这些反斜杠,或者你是在调试器中查看它?如果你使用Console.WriteLine将其转储到控制台中,它会是什么样子? - Jon Skeet
不,它确实包含所有这些斜杠。我已经检查过了。不幸的是,这不是调试器的问题。 - Gonzalioz
即使在使用Chrome浏览器进行API请求时,我仍然会遇到这个问题。 - Gonzalioz
嗯,我有一个想法,但在第227列失败了(我相信这是结尾 - \}不是有效的)。你能联系API生产者吗? - Jon Skeet
啊,那样的话,我可能有一个答案,但我现在不在笔记本电脑旁。一个小时后再试试... - Jon Skeet
显示剩余2条评论
4个回答

31

基本上这就是将 JSON 编码为 JSON 字符串 - 根据评论稍微修改了字符串的末尾。使用 Json.NET 处理它并不太难,可以使用 JToken.Parse 来有效地取消转义,然后解析结果:

using System;
using System.IO;
using Newtonsoft.Json.Linq;

class Program
{
    static void Main(string[] args)
    {
        string text = File.ReadAllText("test.json");
        JToken token = JToken.Parse(text);
        JObject json = JObject.Parse((string) token);
        Console.WriteLine(json);
    }
}

输出:

{
  "SomeResponse": {
    "FIrstAttribute": 8,
    "SecondAttribute": "On",
    "ThirdAttribute": {
      "Id": 2,
      "FirstName": "Okkie",
      "Name": "Bokkie",
      "Street": "",
      "StreetNumber": null,
      "PostCode": "",
      "City": "",
      "Country": ""
    }
  }
}

即使数据包含反斜杠,这应该也没问题,因为我期望反斜杠会再次被编码 - 但最好再确认一下。


4
@SriReddy说:"这是无效的——如果要创建一个带有反斜杠的字符串,你需要在JSON中使用双反斜杠,这意味着在你的字符串字面量中要使用四个反斜杠,例如var text = "{\"PersonName\":\"Gol\\\\ld\"}";但这只有在字面量中才有用,在JSON本身中只有双反斜杠。" - Jon Skeet
5
当将令牌转换为字符串时,对我来说会出现“无法将对象转换为字符串”的错误。 - Shaun Luttin
2
@ShaunLuttin:不清楚您是否指的是文本实际上有反斜杠。如果没有,您应该只使用JObject.Parse(text)。这个问题是关于JSON已经第二次编码为JSON字符串的情况。 - Jon Skeet
1
@Greg:不,这种情况下一个是另一个的包装版本。 - Jon Skeet
1
@GregDegruy:不,令牌的内容是一个有效的JSON字符串,然后被解析为JObject。 - Jon Skeet
显示剩余10条评论

10

通过使用Newtonsoft.Json,这是一个示例:

String json="{\"SomeResponse\":{\"FIrstAttribute\":8,\"SecondAttribute\":\"On\",\"ThirdAttribute\":{\"Id\":2,\"FirstName\":\"Okkie\",\"Name\":\"Bokkie\",\"Street\":\"\",\"StreetNumber\":null,\"PostCode\":\"\",\"City\":\"\",\"Country\":\"}}}";     

dynamic result = JsonConvert.DeserializeObject(json);


0

呃...这根本不是JSON。它是一种奇怪的类JSON模拟,但非常恶心。我认为你正在做正确的事情。

唯一可能要做的就是对字符对执行替换操作,而不仅仅是单个转义字符:

myString.Replace(@"\""", @"""); // 将 \" 替换为 "

这将使您能够安全地保留嵌套的 "\" 字符,以便过滤后的JSON看起来像:

field_blah: "root\branch\sub-branch"

我强烈建议对“JSON”文本进行详细审查,并确保这是您需要担心的唯一成对序列。如果您有其他配对,请按照上述方式处理它们。


0
var JsonRequest = JToken.Parse(rawjson).ToString(Newtonsoft.Json.Formatting.None);

1
你好,欢迎来到stackoverflow。请不要仅仅发布代码作为答案,还需要简要解释你在那里做了什么。除非代码本身已经很清晰易懂,但我在这里并没有看到。 - MichaelJanz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接