jsonjenkinsgroovyjsonslurper

Groovy parse Json preserve keys order


I try to parse a Json in groovy/Jenkins(I have no access to readJSON step) and keep the json keys order.

After my research, I found that groovy Map/HashMap objects are not preserving the order of the keys. The only type which keeping order is LinkedHashMap So I try to convert the output of JsonSlurper.parseText to linkedhashmap but it still changing the items order

def jsonstr = """
{
    "Id": 533,
    "StartTime": "2022-05-10 11:56:18",
    "EndTime": "2022-05-10 11:58:49",
    "TimeShift": "N/A",
    "Run": "123",
    "Setup": "Test",
    "Version": "3.17",
    "Result": "pass",
    "DebugMode": 1,
    "NumberOfCores": 3,
}
"""

//init as LinkedHashMap
LinkedHashMap map = new LinkedHashMap()
map = (LinkedHashMap) (new JsonSlurperClassic().parseText(jsonstr))
println(map)
/*
the output is in incorrect order, I expect to get `Id` attribute as a first key but I'm getting: 
[EndTime:2022-05-10 11:58:49, Version:3.17, TimeShift:N/A, StartTime:2022-05-10 11:56:18, DebugMode:1, Run:123, NumberOfCores:3, Id:533, Setup:Test, Result:pass]
*/



Solution

  • Here is the solution: I realized that readJSON step is keeping the order so I try to take a look at its implementation.

    readJSON uses net.sf.json.* library, in this library there is an option to parse string to jsonObject (with keeping the order of the keys!) by:

    import  net.sf.json.JSONSerializer
    
    def map = JSONSerializer.toJSON(jsonstr)
    println(map)
    

    NOTES:

    1. if you want use it during a pipeline I suggest you to use readJSON step itself, otherwise, you'll need to approve this function from Manage Jenkins -> script approval
    2. In this method empty properties will be net.sf.json.JSONNull which holds a textual value "null" -> if (someEmptyKey != null) always returns true (also when null) to avoid that, use: if (!someEmptyKey instanceof JSONNull )

    Sources: docs, jenkins-implementation