2 回答

TA貢獻1828條經驗 獲得超6個贊
不幸的是,正如您所發現的,無效的 json 是無效的,因此無法由普通和常見的 json (de) 序列化程序(如 Json.net)處理。
對反序列化程序使用轉換器和策略設置也不起作用,因為它們旨在處理諸如空對象作為數組返回或名稱轉換/大小寫處理之類的事情。
一個天真的解決方案是做一個簡單的字符串替換,比如
string?json?=?invalidJson.Replace("False",?"false");
但是,這存在一些問題:
您需要將整個無效的 json 讀入內存,并創建它的固定副本,這意味著您將在內存中擁有兩個完整的數據副本,一個是壞的,一個是好的。
它也會替換內部字符串。這可能不是您的數據問題,但使用上述方法并不容易處理。
False
另一種方法是編寫一個基本的分詞器,該分詞器可以理解基本的 JSON 語法,例如字符串、數字和標識符,并逐個令牌遍歷文件,替換錯誤的標識符。這將解決問題 2,但根據解決方案,可能需要更復雜的實現來修復內存問題 1。
下面發布了一個簡單的嘗試,創建一個可以使用的標識符,這將在找到標識符時修復它們,否則可以理解基本的 JSON 令牌。TextReader
請注意以下幾點:
它不是真正的性能。它始終分配臨時緩沖區。您可能希望研究“緩沖區租用”以更好地處理此方法,甚至只是直接流式傳輸到緩沖區。
它不處理數字,因為那時我停止編寫代碼。我把這個留作練習??梢跃帉懟镜臄底痔幚恚驗槟]有真正驗證文件是否具有有效的 JSON,因此可以添加任何可以獲取足夠字符來構成數字的內容。
我沒有用非常大的文件對此進行測試,只用小的示例文件進行測試。我復制了一個9.5MB的文本,它適用于此。
List<Test>
我沒有測試所有 JSON 語法??赡艽嬖趹撎幚淼刺幚淼淖址?strong>如果您最終使用它,請創建大量測試!
但是,它的作用是根據您發布的標識符修復無效的 JSON,并且它以流式方式執行此操作。因此,無論您的 JSON 文件有多大,這都應該可用。
無論如何,這是代碼,再次注意有關數字的異常:
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貢獻1843條經驗 獲得超7個贊
應在源中修復無效的 json。
如果你真的需要按原樣解析它,如果你想把它作為一個字符串,你可以用“False”替換 False,如果你想把它作為一個布爾值,你可以用 false 替換它。
// If you want a string
json.Replace("False", "\"False\"");
// If you want a bool
json.Replace("False", "false");
一個問題是,如果一個鍵或其他值包含“False”模式。
- 2 回答
- 0 關注
- 247 瀏覽
添加回答
舉報