JSON has become one of the most widely accepted data interchange/representation formats. Not only as a Web data interchange, but also as data representation of multiple document databases.
Justified dumbness
One might question why does one have to write JSON at all since there are libraries for that, right?
The only justified scenario I can find (and the one that lead me to write this entry) is testing.
Writing JSON literals using string formatting (or concatenation) would be a top 5 of “What on Earth are you doing there?” in a code review. But it makes sense if one is verifying that the JSON is properly generated.
Pain in The Neck
Thing is, names in JSON need to be written between double quotes, and so are string values. Since I write tons of C# I have to put up with escaping double quotes in string literals (\"
for normal literals or ""
for verbatim ones). In any case, it is annoying. And when I get annoyed too much, I do something about it.
Working Inspiration
I was working on some MongoDB support for NMoneys (more on this to come in future posts) when, while looking at some of their unit tests, I saw a test like this:
But of course!!!! That is genius! Since I did not come up with it, at least I had to do something. And so I abstracted away the logic to do the replacements, guess a couple of clever names and add some syntactic sugar. And so, JsonString
became a new member of the Testing.Commons family.
Triple Clarification: I am not claiming ownership of the idea, I saw it from the MongoDB guys, which they may or may not have invented “the trick”
Compact JSON Vs. Expansion
I love names, despite being one of the two hardest things in Computer Science.
So how would I name a JSON literal that uses '
instead of escaped "
? I would name it Compact JSON.
And the proper JSON that results from Compact JSON? Expanded JSON.
Using Compact JSON
There are several ways in which this technique can be used.
Instantiating the class
One can pass the Compact JSON literal to the JsonString
constructor. From then one, one can get the expanded JSON by either invoking .ToString()
or by passing the instance whenever a string is expected via implicit conversion.
Extension method
Invoke the .Jsonify()
extension method on the Compact JSON literal to get the expanded JSON as a string.
Asserting Compact JSON
I mentioned one should avoid writing JSON literals (except when testing). In that case one is more likely to be using those literals while asserting the result of one’s code.
Then it makes sense that Testing.Commons.NUnit contains a JsonEqualConstraint
.
Using the Constraint Directly
Using the Must Extensibility Model
Modifying EqualConstraint
Our last option would be continue using the EqualConstraint
, but changing how it behaves via a custom IEqualityComparer<>
encapsulated in the extension method .AsJson()