Grails’ JSONObject.NULL More or Less Equal To Null
Since Groovy 1.8 we can check if a Map is equal to another Map if the keys and values are the same. Very convenient in tests for example.
def someMap = [age: 34, name: "Ted"] assert someMap == [name: "Ted", age: 34]
Today I kept staring at a failure, while testing some x and y graph data points returned by a Grails controller, where two Maps were somehow not equal according to Spock, while even the assertion’s output looked ‘equal’.
when: controller.milkYield() then: response.json and: "series are present" def series = response.json series.size() == 2 and: "realized series is correct" ... and: "predicted series is correct" def predictedSeries = series[1] predictedSeries.values.size() == 2 predictedSeries.values[0] == [y:null, x:'Mar'] predictedSeries.values[1] == [y:121, x:'Apr']
resulted in:
Condition not satisfied: predictedSeries.values[0] == [y:null, x:'Mar'] | | | | | | | false | | [y:null, x:Mar] | [[y:null, x:Mar], [y:121, x:Apr]] [values:[[y:null, x:Mar], [y:121, x:Apr]]]
Why isn’t [y:null, x:Mar]
equal to [y:null, x:Mar]
?
After having checked explicitly with
predictedSeries.values[0].x == 'Mar' predictedSeries.values[0].y == null // <- better be null!
I remembered again I was dealing with JSON data in Grails, which uses the Null Object pattern. Keeps biting me every now and then :-)
Condition not satisfied: predictedSeries.values[0].y == null | | | | | | | | | false | | | null (org.codehaus.groovy.grails.web.json.JSONObject$Null) | | [y:null, x:Mar] | [[y:null, x:Mar], [y:121, x:Apr]] [values:[[y:null, x:Mar], [y:121, x:Apr]]]
It’s a JSONObject$Null
instance. It exists because it’s equivalent to the value that JavaScript calls null, whilst Java’s null is equivalent to the value that JavaScript calls undefined.
There are some long time posts already describing this behaviour that JSONObject.NULL
was not equal to null
…
JSONObject.NULL.equals(null) // true JSONObject.NULL == null // false!!
and some meta-class changes you could do were suggested at the time. Seems reported GRAILS-7739 (Wrong == and asBoolean behavior for JSONObject.Null) says it’s been fixed a few years back in Grails 2.2.
Atleast something has been fixed. Although you still can not do JSONObject.NULL == null
, you can change the assertion to using Groovy Truth since !JSONObject.NULL
does work.
!predictedSeries.values[0].y // or predictedSeries.values[0] == [y: JSONObject.NULL, x:'Mar'] if you like
And of course I should remember null in (console) output is always a String representation leading to “null” – such as JSONObject.NULL
‘s toString()
returns.
Reference: | Grails’ JSONObject.NULL More or Less Equal To Null from our JCG partner Ted Vinke at the Ted Vinke’s Blog blog. |