Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exclude null values using JSONBuilder in Groovy

Is it possible to create JSON values in Groovy using the default JsonBuilder library to exclude all the null values of an object? Such as what Jackson does in Java by annotating classes to exclude null values.

An example would be:

{
   "userId": "25",
   "givenName": "John",
   "familyName": null,
   "created": 1360080426303
}

Which should be printed as:

{
   "userId": "25",
   "givenName": "John",
   "created": 1360080426303
}
like image 657
Peymankh Avatar asked Feb 07 '13 11:02

Peymankh


People also ask

What is JsonBuilder in Groovy?

public class JsonBuilder extends GroovyObjectSupport implements Writable A builder for creating JSON payloads. This builder supports the usual builder syntax made of nested method calls and closures, but also some specific aspects of JSON data structures, such as list of values, etc.

How to serialize Groovy objects into JSON strings?

Structures such as maps, lists and primitive types like Integer, Double, Boolean and String. This method is responsible for serialising Groovy objects into JSON strings. JsonSlurper is a class that parses JSON text or reader content into Groovy data Structures such as maps, lists and primitive types like Integer, Double, Boolean and String.

What is JSON slurper in Groovy?

JsonSlurper is a class that parses JSON text or reader content into Groovy data Structures such as maps, lists and primitive types like Integer, Double, Boolean and String. JSON slurper parses text or reader content into a data structure of lists and maps.

How does jsonslurper handle null values in JSON?

Whenever a value in JSON is null, JsonSlurper supplements it with the Groovy null value. This is in contrast to other JSON parsers that represent a null value with a library-provided singleton object.


3 Answers

Not sure if it's OK for you as my method works on a Map with List properties:

def map = [a:"a",b:"b",c:null,d:["a1","b1","c1",null,[d1:"d1",d2:null]]]

def denull(obj) {
  if(obj instanceof Map) {
    obj.collectEntries {k, v ->
      if(v) [(k): denull(v)] else [:]
    }
  } else if(obj instanceof List) {
    obj.collect { denull(it) }.findAll { it != null }
  } else {
    obj
  }
}

println map
println denull(map)

yields:

[a:a, b:b, c:null, d:[a1, b1, c1, null, [d1:d1, d2:null]]]
[a:a, b:b, d:[a1, b1, c1, [d1:d1]]]

After filter null values out, you then can render the Map as JSON.

like image 109
chanwit Avatar answered Nov 01 '22 12:11

chanwit


I used the Groovy metaClass to workaround this issue, but am not sure it would work in all cases.

I created a Class to hold the required elements, but left out the optional elements that could possibly have a null (or empty) value.

private class User {
    def id
    def username
}

Then, I added the data to this class. My use case was fairly complex so this is a simplified version just to show an example of what I did:

User a = new User(id: 1, username: 'john')
User b = new User(id: 2, username: 'bob')
def usersList = [a,b]

usersList.each { u ->
    if (u.id == 1)
        u.metaClass.hobbies = ['fishing','skating']
}
def jsonBuilder = new JsonBuilder([users: usersList])
println jsonBuilder.toPrettyString()

Results:

{
"users": [
    {
        "id": 1,
        "username": "john",
        "hobbies": [
            "fishing",
            "skating"
        ]
    },
    {
        "id": 2,
        "username": "bob"
    }
  ]
}
like image 22
acvcu Avatar answered Nov 01 '22 11:11

acvcu


If you do not need use JSONBuilder you can use com.fasterxml.jackson:

Make object:

private static final ObjectMapper JSON_MAPPER = new ObjectMapper().with {
    setSerializationInclusion(JsonInclude.Include.NON_NULL)
    setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY)
    setVisibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.NONE)
    setVisibility(PropertyAccessor.IS_GETTER, JsonAutoDetect.Visibility.NONE)
}

and display your list of maps like that (maps can have any Object inside):

println(JSON_MAPPER.writeValueAsString(listOfMaps))
like image 29
Grzegorz Medias Avatar answered Nov 01 '22 11:11

Grzegorz Medias