Исключить пустые значения с помощью JSONBuilder в Groovy

Можно ли создать значения JSON в Groovy, используя библиотеку JsonBuilder по умолчанию, чтобы исключить все нулевые значения объекта? Например, то, что Джексон делает в Java, аннотируя классы, чтобы исключить нулевые значения.

Примером может быть:

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

Что должно быть напечатано как:

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

person Peymankh    schedule 07.02.2013    source источник
comment
Вам нужно, чтобы он был рекурсивным?   -  person Will    schedule 07.02.2013
comment
@WillP Да. Потому что он может иметь списки или карты, встроенные в объект.   -  person Peymankh    schedule 07.02.2013
comment
Вы используете синтаксис закрытия или синтаксис карты для вложенных структур?   -  person Will    schedule 07.02.2013
comment
@WillP На данный момент я использую синтаксис карты, но, если возможно, могу переключиться на закрытие.   -  person Peymankh    schedule 07.02.2013


Ответы (4)


Не уверен, что это нормально для вас, поскольку мой метод работает с Map со свойствами List:

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)

дает:

[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]]]

После фильтрации значений null вы можете отобразить Map как JSON.

person chanwit    schedule 07.02.2013
comment
Спасибо за ответ. Я это попробую. - person Peymankh; 08.02.2013
comment
это хороший ответ, но лучший способ сделать это - заменить List на Collection. Таким образом, все элементы коллекции, включая наборы, будут обнулены! - person Peymankh; 02.10.2015
comment
Спасибо за ответ @chanwit, очень полезно! - person Vishal Biyani; 15.02.2017

Я использовал метакласс Groovy, чтобы обойти эту проблему, но не уверен, что он будет работать во всех случаях.

Я создал класс для хранения необходимых элементов, но исключил необязательные элементы, которые могли иметь нулевое (или пустое) значение.

private class User {
    def id
    def username
}

Затем я добавил данные в этот класс. Мой вариант использования был довольно сложным, поэтому это упрощенная версия, чтобы показать пример того, что я сделал:

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()

Полученные результаты:

{
"users": [
    {
        "id": 1,
        "username": "john",
        "hobbies": [
            "fishing",
            "skating"
        ]
    },
    {
        "id": 2,
        "username": "bob"
    }
  ]
}
person acvcu    schedule 02.04.2015

Если вам не нужно использовать JSONBuilder, вы можете использовать com.fasterxml.jackson:

Сделать объект:

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)
}

и отобразите свой список карт таким образом (карты могут иметь любой объект внутри):

println(JSON_MAPPER.writeValueAsString(listOfMaps))
person Grzegorz Medias    schedule 24.01.2018

Если вы используете Groovy > 2.5.0, вы можете использовать JsonGenerator. Пример ниже взят из документации Groovy по состоянию на июль 2018 г.

class Person {
    String name
    String title
    int age
    String password
    Date dob
    URL favoriteUrl
}

Person person = new Person(name: 'John', title: null, age: 21, password: 'secret',
                            dob: Date.parse('yyyy-MM-dd', '1984-12-15'),
                            favoriteUrl: new URL('http://groovy-lang.org/'))

def generator = new JsonGenerator.Options()
    .excludeNulls()
    .dateFormat('yyyy@MM')
    .excludeFieldsByName('age', 'password')
    .excludeFieldsByType(URL)
    .build()

assert generator.toJson(person) == '{"dob":"1984@12","name":"John"}'
person krismath    schedule 06.07.2018