过滤 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 个匹配项,包括一对 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);