2 回答

TA貢獻(xiàn)1828條經(jīng)驗(yàn) 獲得超6個(gè)贊
不幸的是,正如您所發(fā)現(xiàn)的,無效的 json 是無效的,因此無法由普通和常見的 json (de) 序列化程序(如 Json.net)處理。
對(duì)反序列化程序使用轉(zhuǎn)換器和策略設(shè)置也不起作用,因?yàn)樗鼈冎荚谔幚碇T如空對(duì)象作為數(shù)組返回或名稱轉(zhuǎn)換/大小寫處理之類的事情。
一個(gè)天真的解決方案是做一個(gè)簡(jiǎn)單的字符串替換,比如
string?json?=?invalidJson.Replace("False",?"false");
但是,這存在一些問題:
您需要將整個(gè)無效的 json 讀入內(nèi)存,并創(chuàng)建它的固定副本,這意味著您將在內(nèi)存中擁有兩個(gè)完整的數(shù)據(jù)副本,一個(gè)是壞的,一個(gè)是好的。
它也會(huì)替換內(nèi)部字符串。這可能不是您的數(shù)據(jù)問題,但使用上述方法并不容易處理。
False
另一種方法是編寫一個(gè)基本的分詞器,該分詞器可以理解基本的 JSON 語法,例如字符串、數(shù)字和標(biāo)識(shí)符,并逐個(gè)令牌遍歷文件,替換錯(cuò)誤的標(biāo)識(shí)符。這將解決問題 2,但根據(jù)解決方案,可能需要更復(fù)雜的實(shí)現(xiàn)來修復(fù)內(nèi)存問題 1。
下面發(fā)布了一個(gè)簡(jiǎn)單的嘗試,創(chuàng)建一個(gè)可以使用的標(biāo)識(shí)符,這將在找到標(biāo)識(shí)符時(shí)修復(fù)它們,否則可以理解基本的 JSON 令牌。TextReader
請(qǐng)注意以下幾點(diǎn):
它不是真正的性能。它始終分配臨時(shí)緩沖區(qū)。您可能希望研究“緩沖區(qū)租用”以更好地處理此方法,甚至只是直接流式傳輸?shù)骄彌_區(qū)。
它不處理數(shù)字,因?yàn)槟菚r(shí)我停止編寫代碼。我把這個(gè)留作練習(xí)??梢跃帉懟镜臄?shù)字處理,因?yàn)槟]有真正驗(yàn)證文件是否具有有效的 JSON,因此可以添加任何可以獲取足夠字符來構(gòu)成數(shù)字的內(nèi)容。
我沒有用非常大的文件對(duì)此進(jìn)行測(cè)試,只用小的示例文件進(jìn)行測(cè)試。我復(fù)制了一個(gè)9.5MB的文本,它適用于此。
List<Test>
我沒有測(cè)試所有 JSON 語法??赡艽嬖趹?yīng)該處理但未處理的字符。如果您最終使用它,請(qǐng)創(chuàng)建大量測(cè)試!
但是,它的作用是根據(jù)您發(fā)布的標(biāo)識(shí)符修復(fù)無效的 JSON,并且它以流式方式執(zhí)行此操作。因此,無論您的 JSON 文件有多大,這都應(yīng)該可用。
無論如何,這是代碼,再次注意有關(guān)數(shù)字的異常:
void Main()
{
? ? using (var file = File.OpenText(@"d:\temp\test.json"))
? ? using (var fix = new MyFalseFixingTextReader(file))
? ? {
? ? ? ? var reader = new JsonTextReader(fix);
? ? ? ? var serializer = new JsonSerializer();
? ? ? ? serializer.Deserialize<Test>(reader).Dump();
? ? }
}
public class MyFalseFixingTextReader : TextReader
{
? ? private readonly TextReader _Reader;
? ? private readonly StringBuilder _Buffer = new StringBuilder(32768);
? ? public MyFalseFixingTextReader(TextReader reader) => _Reader = reader;
? ? public override void Close()
? ? {
? ? ? ? _Reader.Close();
? ? ? ? base.Close();
? ? }
? ? public override int Read(char[] buffer, int index, int count)
? ? {
? ? ? ? TryFillBuffer(count);
? ? ? ? int amountToCopy = Math.Min(_Buffer.Length, count);
? ? ? ? _Buffer.CopyTo(0, buffer, index, amountToCopy);
? ? ? ? _Buffer.Remove(0, amountToCopy);
? ? ? ? return amountToCopy;
? ? }
? ? private (bool more, char c) TryReadChar()
? ? {
? ? ? ? int i = _Reader.Read();
? ? ? ? if (i < 0)
? ? ? ? ? ? return (false, default);
? ? ? ? return (true, (char)i);
? ? }
? ? private (bool more, char c) TryPeekChar()
? ? {
? ? ? ? int i = _Reader.Peek();
? ? ? ? if (i < 0)
? ? ? ? ? ? return (false, default);
? ? ? ? return (true, (char)i);
? ? }
? ? private void TryFillBuffer(int count)
? ? {
? ? ? ? if (_Buffer.Length >= count)
? ? ? ? ? ? return;
? ? ? ? while (_Buffer.Length < count)
? ? ? ? {
? ? ? ? ? ? var (more, c) = TryPeekChar();
? ? ? ? ? ? if (!more)
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? switch (c)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? case '{':
? ? ? ? ? ? ? ? case '}':
? ? ? ? ? ? ? ? case '[':
? ? ? ? ? ? ? ? case ']':
? ? ? ? ? ? ? ? case '\r':
? ? ? ? ? ? ? ? case '\n':
? ? ? ? ? ? ? ? case ' ':
? ? ? ? ? ? ? ? case '\t':
? ? ? ? ? ? ? ? case ':':
? ? ? ? ? ? ? ? case ',':
? ? ? ? ? ? ? ? ? ? _Reader.Read();
? ? ? ? ? ? ? ? ? ? _Buffer.Append(c);
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? case '"':
? ? ? ? ? ? ? ? ? ? _Buffer.Append(GrabString());
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? case char letter when char.IsLetter(letter):
? ? ? ? ? ? ? ? ? ? var identifier = GrabIdentifier();
? ? ? ? ? ? ? ? ? ? _Buffer.Append(ReplaceFaultyIdentifiers(identifier));
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? case char startOfNumber when startOfNumber == '-' || (startOfNumber >= '0' && startOfNumber <= '9'):
? ? ? ? ? ? ? ? ? ? _Buffer.Append(GrabNumber());
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? default:
? ? ? ? ? ? ? ? ? ? throw new InvalidOperationException($"Unable to cope with character '{c}' (0x{((int)c).ToString("x2")})");
? ? ? ? ? ? }
? ? ? ? }
? ? }
? ? private string ReplaceFaultyIdentifiers(string identifier)
? ? {
? ? ? ? switch (identifier)
? ? ? ? {
? ? ? ? ? ? case "False":
? ? ? ? ? ? ? ? return "false";
? ? ? ? ? ? case "True":
? ? ? ? ? ? ? ? return "true";
? ? ? ? ? ? case "Null":
? ? ? ? ? ? ? ? return "null";
? ? ? ? ? ? default:
? ? ? ? ? ? ? ? return identifier;
? ? ? ? }
? ? }
? ? private string GrabNumber()
? ? {
? ? ? ? throw new NotImplementedException("Left as an excercise");
? ? ? ? // See https://www.json.org/ for the syntax
? ? }
? ? private string GrabIdentifier()
? ? {
? ? ? ? var result = new StringBuilder();
? ? ? ? while (true)
? ? ? ? {
? ? ? ? ? ? int i = _Reader.Peek();
? ? ? ? ? ? if (i < 0)
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? char c = (char)i;
? ? ? ? ? ? if (char.IsLetter(c))
? ? ? ? ? ? {
? ? ? ? ? ? ? ? _Reader.Read();
? ? ? ? ? ? ? ? result.Append(c);
? ? ? ? ? ? }
? ? ? ? ? ? else
? ? ? ? ? ? ? ? break;
? ? ? ? }
? ? ? ? return result.ToString();
? ? }
? ? private string GrabString()
? ? {
? ? ? ? _Reader.Read();
? ? ? ? var result = new StringBuilder();
? ? ? ? result.Append('"');
? ? ? ? while (true)
? ? ? ? {
? ? ? ? ? ? var (more, c) = TryReadChar();
? ? ? ? ? ? if (!more)
? ? ? ? ? ? ? ? return result.ToString();
? ? ? ? ? ? switch (c)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? case '"':
? ? ? ? ? ? ? ? ? ? result.Append(c);
? ? ? ? ? ? ? ? ? ? return result.ToString();
? ? ? ? ? ? ? ? case '\\':
? ? ? ? ? ? ? ? ? ? result.Append(c);
? ? ? ? ? ? ? ? ? ? (more, c) = TryReadChar();
? ? ? ? ? ? ? ? ? ? if (!more)
? ? ? ? ? ? ? ? ? ? ? ? return result.ToString();
? ? ? ? ? ? ? ? ? ? switch (c)
? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? case 'u':
? ? ? ? ? ? ? ? ? ? ? ? ? ? result.Append(c);
? ? ? ? ? ? ? ? ? ? ? ? ? ? for (int index = 1; index <= 4; index++)
? ? ? ? ? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (more, c) = TryReadChar();
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if (!more)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? return result.ToString();
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? result.Append(c);
? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? ? ? ? ? default:
? ? ? ? ? ? ? ? ? ? ? ? ? ? result.Append(c);
? ? ? ? ? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? default:
? ? ? ? ? ? ? ? ? ? result.Append(c);
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? }
? ? ? ? }
? ? }
}
public class Test
{
? ? public bool False1 { get; set; }
? ? public bool False2 { get; set; }
? ? public bool False3 { get; set; }
}
示例文件:
{
? ? "false1": false,
? ? "false2": "false",
? ? "false3": False
}
輸出:

TA貢獻(xiàn)1843條經(jīng)驗(yàn) 獲得超7個(gè)贊
應(yīng)在源中修復(fù)無效的 json。
如果你真的需要按原樣解析它,如果你想把它作為一個(gè)字符串,你可以用“False”替換 False,如果你想把它作為一個(gè)布爾值,你可以用 false 替換它。
// If you want a string
json.Replace("False", "\"False\"");
// If you want a bool
json.Replace("False", "false");
一個(gè)問題是,如果一個(gè)鍵或其他值包含“False”模式。
- 2 回答
- 0 關(guān)注
- 257 瀏覽
添加回答
舉報(bào)