0

I have a JSON file where I have data types as integer, array, string etc … issue happens while reading file in C# when array property for one of my valid JSON has data like this "power":[-INF, -INF, 6,-8.98].

Now I know, modern JSON parser do not support -INF value and that is why this error occurs. So one workaround will be to replace -INF in my data file to something like "-Infinity".
Can someone help me with an optimized code where I read the file and replace the -INF without breaking anything else in the JSON file before doing any further transformation.

Sample of my JSON file

{
  "AppVersion":"testb0d",
  "Bin":"P",
  "FailCounts":[-INF,-INF,-INF,-INF,3.223622,-3.111,12,0,0]
}
Panagiotis Kanavos
  • 120,703
  • 13
  • 188
  • 236
ZZZSharePoint
  • 1,163
  • 1
  • 19
  • 54
  • Shouldn't you fix the code that produced that `-INF` instead? The JSON standard explicitly forbids implementation-dependent concepts like Infinity: `Numeric values that cannot be represented in the grammar below (such as Infinity and NaN) are not permitted.`. Besides, the very idea of `-INF` for something called `FailCounts` is wrong and probably resulted from incorrect division by zero. If a value is missing, use `NULL`. – Panagiotis Kanavos May 31 '21 at 11:11
  • 3
    "*I have a .jsonl file(i.e each line with a valid json)...*" Technically, [it is *not* valid json](https://stackoverflow.com/a/13582027/87698). So, actually, you are asking how to convert something that "looks like JSON but isn't" into valid JSON. – Heinzi May 31 '21 at 11:11
  • It's not valid JSON not because there's one document per line. It's invalid because it contains invalid strings like `-INF`. It's a *very* common and old practice to store one document per line for streaming purposes - so much so that people have tried to hijack this common practice by trying to stick their own names to it. There's no `jsonl`, no `ndjson`, no `jsonlines` standard or format. All refer to something people already did for a long time - store one unindented json document per line – Panagiotis Kanavos May 31 '21 at 11:12
  • @Panagiotis cant change the source , its nt possible for now(we already had discussed that option) Don't go on Fail counts and other terms in there, I just wanted to give a idea of data, how it looks like. if I take a loop for each lines Jsonl files, i get a valid json which I am able to parse using newtonsoft. so lets say I have a valid Json file with -INF data – ZZZSharePoint May 31 '21 at 11:20
  • Please don't insist that the invalid `-INF` value is valid in any way. That's what prevents you from solving this. Since it's *invalid*, you can't use any parser out of the box. You'll have to write your own custom converter for that property and apply it [with an attribute](https://www.newtonsoft.com/json/help/html/JsonConverterAttributeProperty.htm). You didn't post your code, classes or explain that you use JSON.NET otherwise people may already have suggested that solution – Panagiotis Kanavos May 31 '21 at 11:22
  • You [already asked the same question](https://stackoverflow.com/questions/67681756/error-parsing-infinity-value-in-json-deserialization) . What's the point of making a duplicate question? It won't change the answer – Panagiotis Kanavos May 31 '21 at 11:29
  • first because didn't get an answer , second, was not sure about solution so here I hv asked for an approach for a solution – ZZZSharePoint May 31 '21 at 11:56

1 Answers1

0

Just a minor nitpick first: "I have a .jsonl file(i.e each line with a valid json)..." Technically, it is not valid json, since -INF is disallowed by the JSON standard. So, actually, you are asking how to convert something that "looks like JSON but isn't" into valid JSON.

That having been said, you basically want to replace all -INF by a valid JSON value (e.g. 0 or "-INF"). You need to ignore -INF inside quotes, since it might occur (validly) inside a string or a member name.

Unfortunately, JSON allows for escaped quotes (\"), which makes matters more complicated. Surprisingly, I did not find a ready-made implementation here on SO which (a) replaces text only if it occurs outside of double quotes and (b) can deal with C-style escaped quotes. However, the implementation of such a parser should be fairly straightforward, I'll give you some pseudo-code to get you started:

insideQuotes = false

loop through chars:

    if char = '\':
       skip next char       // this is necessary to ignore escaped quotes

    else if char = '"':
       toggle insideQuotes

    else if not insideQuotes and the next 4 chars are "-INF":
       replace them
Heinzi
  • 167,459
  • 57
  • 363
  • 519