过滤 json 字符串中的无效值
filter invalid values in json string
我正在 html 正文中获取一个字符串,我正在尝试将其处理为有效 json。我收到的字符串不是有效的 json 字符串并且包含以下架构:
äÄ
"key1": " 10",
"key2": "beigef}gtem Zahlschein",
"key3": " G E L \ S C H T",
"key4": "M}nchen",
"key5": "M{rz",
"key6": "[huus"
Ü
ä
我已经编写了一个函数来替换所有错误字符以创建有效的 json 字符串,但是我如何在不破坏 json 中所需的字母的情况下进行反向操作?
我是这样替换字符的:
private static string FixChars(string input)
{
if (!string.IsNullOrEmpty(input))
{
if (input.Contains("["))
{
input = input.Replace("[", "Ä");
}
if (input.Contains(@"\"))
{
input = input.Replace(@"\", "Ö");
}
if (input.Contains("]"))
{
input = input.Replace("]", "Ü");
}
if (input.Contains("{"))
{
input = input.Replace("{", "ä");
}
if (input.Contains("|"))
{
input = input.Replace("|", "ö");
}
if (input.Contains("}"))
{
input = input.Replace("}", "ü");
}
if (input.Contains("~"))
{
input = input.Replace("~", "ß");
}
//DS_Stern hat Probleme beim xml erstellen gemacht
//if (input.Contains("*"))
//{
// input = input.Replace("*", "Stern");
//}
}
return input;
}
然后我尝试将 json 数组反序列化为这样的字典:
deserializedRequest = JsonConvert.DeserializeObject<Dictionary<string, string>[]>(json);
如何访问不同的词典,对值使用我的 FixChars 方法并从中重新序列化有效的 json 字符串?
编辑:IBM273 和通过 IBM037 解码可以很好地创建有效的 json 字符串,但仍然包含一个小错误:字符 'ö' 是 '|'在那个编码中。
看起来包含您的 JSON 的 HTML 页面在您的 Unisys A 系列机器 (cobol74)[=41= 上编码为字节流] 使用一个 encoding 然后由您的代码使用不同的编码解码,从而导致某些字符被重新映射或丢失。要解决您的问题,您需要确定该 Unisys 计算机上使用的原始编码,并使用它解码 HTML 流。让事情变得更复杂的是,我们不确定 .Net 选择哪种编码来解码 HTML。
做出决定的一种方法是对预期 JSON 进行采样,然后使用 .网。如果任何一对编码产生了您所看到的不正确结果,那么用于对字符串进行编码的编码可能就是 Unisys 计算机上使用的编码。并且,通过反转转换,假设没有删除任何字符,您可以修复字符串。
以下代码执行此测试:
var correctString = "{}[]";
var observedString = "äüÄÜ";
int count = 0;
foreach (var toEncoding in Encoding.GetEncodings())
foreach (var fromEncoding in Encoding.GetEncodings())
{
var s = toEncoding.GetEncoding().GetString(fromEncoding.GetEncoding().GetBytes(correctString));
if (s == observedString)
{
Console.WriteLine(string.Format("Match Found: Encoding via {0} and decoding via {1}", fromEncoding.Name, toEncoding.Name));
count++;
}
}
Console.WriteLine("Found {0} matches", count);
这会产生 147 个匹配项,包括一对 ebcdic encodings. For the full list see this fiddle。
接下来,让我们尝试通过测试完整的 JSON 字符串来减少匹配:
var correctJson = @"{[
""key1"": "" 10"",
""key2"": ""beigefügtem Zahlschein"",
""key3"": "" G E L Ö S C H T"",
""key4"": ""München"",
""key5"": ""März"",
""key6"": ""Ähuus"",
""key7"": ""ö"",
""key8"": ""ß"",
]
{";
var observedJson = @"äÄ
""key1"": "" 10"",
""key2"": ""beigef}gtem Zahlschein"",
""key3"": "" G E L \ S C H T"",
""key4"": ""M}nchen"",
""key5"": ""M{rz"",
""key6"": ""[huus"",
""key7"": ""|"",
""key8"": ""~"",
Ü
ä";
int count = 0;
foreach (var toEncoding in Encoding.GetEncodings())
foreach (var fromEncoding in Encoding.GetEncodings())
{
var s = toEncoding.GetEncoding().GetString(fromEncoding.GetEncoding().GetBytes(correctJson));
if (s == observedJson)
{
Console.WriteLine(string.Format("Match Found: Encoding via {0} and decoding via {1}", fromEncoding.Name, toEncoding.Name));
count++;
}
}
Console.WriteLine("Found {0} matches", count);
这只产生 2 个 EBCDIC 匹配项:
Match Found: Encoding via IBM01141 and decoding via IBM870
Match Found: Encoding via IBM273 and decoding via IBM870
所以其中一个几乎可以肯定是正确的编码对。但是,哪一个?根据wikipedia:
CCSID 1141 is the Euro currency update of code page/CCSID 273. In that code page, the "¤" (currency) character at code point 9F is replaced with the "€" (Euro) character.
因此,要将编码范围缩小到单一选择,您需要使用“€”字符测试样本。
然后如果我添加以下扩展方法:
public static class TextExtensions
{
public static string Reencode(this string s, Encoding toEncoding, Encoding fromEncoding)
{
return toEncoding.GetString(fromEncoding.GetBytes(s));
}
}
我可以通过以下方式修复您的 JSON:
var fixedJson = observedJson.Reencode(Encoding.GetEncoding("IBM01141"), Encoding.GetEncoding("IBM870"));
Console.WriteLine(fixedJson);
我正在 html 正文中获取一个字符串,我正在尝试将其处理为有效 json。我收到的字符串不是有效的 json 字符串并且包含以下架构:
äÄ
"key1": " 10",
"key2": "beigef}gtem Zahlschein",
"key3": " G E L \ S C H T",
"key4": "M}nchen",
"key5": "M{rz",
"key6": "[huus"
Ü
ä
我已经编写了一个函数来替换所有错误字符以创建有效的 json 字符串,但是我如何在不破坏 json 中所需的字母的情况下进行反向操作?
我是这样替换字符的:
private static string FixChars(string input)
{
if (!string.IsNullOrEmpty(input))
{
if (input.Contains("["))
{
input = input.Replace("[", "Ä");
}
if (input.Contains(@"\"))
{
input = input.Replace(@"\", "Ö");
}
if (input.Contains("]"))
{
input = input.Replace("]", "Ü");
}
if (input.Contains("{"))
{
input = input.Replace("{", "ä");
}
if (input.Contains("|"))
{
input = input.Replace("|", "ö");
}
if (input.Contains("}"))
{
input = input.Replace("}", "ü");
}
if (input.Contains("~"))
{
input = input.Replace("~", "ß");
}
//DS_Stern hat Probleme beim xml erstellen gemacht
//if (input.Contains("*"))
//{
// input = input.Replace("*", "Stern");
//}
}
return input;
}
然后我尝试将 json 数组反序列化为这样的字典:
deserializedRequest = JsonConvert.DeserializeObject<Dictionary<string, string>[]>(json);
如何访问不同的词典,对值使用我的 FixChars 方法并从中重新序列化有效的 json 字符串?
编辑:IBM273 和通过 IBM037 解码可以很好地创建有效的 json 字符串,但仍然包含一个小错误:字符 'ö' 是 '|'在那个编码中。
看起来包含您的 JSON 的 HTML 页面在您的 Unisys A 系列机器 (cobol74)[=41= 上编码为字节流] 使用一个 encoding 然后由您的代码使用不同的编码解码,从而导致某些字符被重新映射或丢失。要解决您的问题,您需要确定该 Unisys 计算机上使用的原始编码,并使用它解码 HTML 流。让事情变得更复杂的是,我们不确定 .Net 选择哪种编码来解码 HTML。
做出决定的一种方法是对预期 JSON 进行采样,然后使用 .网。如果任何一对编码产生了您所看到的不正确结果,那么用于对字符串进行编码的编码可能就是 Unisys 计算机上使用的编码。并且,通过反转转换,假设没有删除任何字符,您可以修复字符串。
以下代码执行此测试:
var correctString = "{}[]";
var observedString = "äüÄÜ";
int count = 0;
foreach (var toEncoding in Encoding.GetEncodings())
foreach (var fromEncoding in Encoding.GetEncodings())
{
var s = toEncoding.GetEncoding().GetString(fromEncoding.GetEncoding().GetBytes(correctString));
if (s == observedString)
{
Console.WriteLine(string.Format("Match Found: Encoding via {0} and decoding via {1}", fromEncoding.Name, toEncoding.Name));
count++;
}
}
Console.WriteLine("Found {0} matches", count);
这会产生 147 个匹配项,包括一对 ebcdic encodings. For the full list see this fiddle。
接下来,让我们尝试通过测试完整的 JSON 字符串来减少匹配:
var correctJson = @"{[
""key1"": "" 10"",
""key2"": ""beigefügtem Zahlschein"",
""key3"": "" G E L Ö S C H T"",
""key4"": ""München"",
""key5"": ""März"",
""key6"": ""Ähuus"",
""key7"": ""ö"",
""key8"": ""ß"",
]
{";
var observedJson = @"äÄ
""key1"": "" 10"",
""key2"": ""beigef}gtem Zahlschein"",
""key3"": "" G E L \ S C H T"",
""key4"": ""M}nchen"",
""key5"": ""M{rz"",
""key6"": ""[huus"",
""key7"": ""|"",
""key8"": ""~"",
Ü
ä";
int count = 0;
foreach (var toEncoding in Encoding.GetEncodings())
foreach (var fromEncoding in Encoding.GetEncodings())
{
var s = toEncoding.GetEncoding().GetString(fromEncoding.GetEncoding().GetBytes(correctJson));
if (s == observedJson)
{
Console.WriteLine(string.Format("Match Found: Encoding via {0} and decoding via {1}", fromEncoding.Name, toEncoding.Name));
count++;
}
}
Console.WriteLine("Found {0} matches", count);
这只产生 2 个 EBCDIC 匹配项:
Match Found: Encoding via IBM01141 and decoding via IBM870
Match Found: Encoding via IBM273 and decoding via IBM870
所以其中一个几乎可以肯定是正确的编码对。但是,哪一个?根据wikipedia:
CCSID 1141 is the Euro currency update of code page/CCSID 273. In that code page, the "¤" (currency) character at code point 9F is replaced with the "€" (Euro) character.
因此,要将编码范围缩小到单一选择,您需要使用“€”字符测试样本。
然后如果我添加以下扩展方法:
public static class TextExtensions
{
public static string Reencode(this string s, Encoding toEncoding, Encoding fromEncoding)
{
return toEncoding.GetString(fromEncoding.GetBytes(s));
}
}
我可以通过以下方式修复您的 JSON:
var fixedJson = observedJson.Reencode(Encoding.GetEncoding("IBM01141"), Encoding.GetEncoding("IBM870"));
Console.WriteLine(fixedJson);