Search code examples
jsongroovyjsonbuilder

Adding information from one JsonBuilder object to another


As the title suggests, I'm trying to add information held in one JsonBuilder object to a second JsonBuilder object.

Currently I have this:

public String buildOneUser(DyveUserDTO user)
{
    def userBuilder = new JsonBuilder()
        userBuilder user.collect { usr ->
            [
                    'Name': usr.userName,
                    'Allowance': usr.allowance,
                    'Total Holidays in Calendar': usr.totalHolidaysInCal,
                    'Holidays Booked': usr.numHolidaysBooked,
                    'Holidays Taken': usr.numHolidaysTaken,
                    'Holidays Remaining': usr.totalHolidaysLeft
            ]
        }

    def userHolidayBuilder = new JsonBuilder()
        userHolidayBuilder user.holidayEvents.collect { usr ->
            [
                    'Start Date': usr.startDate,
                    'End Date': usr.endDate,
                    'Days': usr.days
            ]
        }

    def userAndHolidays = userBuilder + userHolidayBuilder

    return userAndHolidays.toPrettyString()
}

user.holidayEvents is a list of objects representing holidays and it could be empty or have any number of objects in it. This made me hesitant of doing something like:

def userBuilder = new JsonBuilder()
        userBuilder user.collect { usr ->
            [
                    'Name': usr.userName,
                    'Allowance': usr.allowance,
                    'Total Holidays in Calendar': usr.totalHolidaysInCal,
                    'Holidays Booked': usr.numHolidaysBooked,
                    'Holidays Taken': usr.numHolidaysTaken,
                    'Holidays Remaining': usr.totalHolidaysLeft
                    'Holiday': usr.holidayEvents[0].startDate
                    'Holiday': usr.holidayEvents[0].endDate
                    'Holiday': usr.holidayEvents[0].days
            ]
        }

As I would only get the amount of holidays I write code for. It would also throw an exception if a user had no holidays and I told it look at usr.holidayEvents[1] as it's outside of the list range.

I've also tried nesting a .collect like this

def userBuilder = new JsonBuilder()
        userBuilder {
           'Name' user.userName,
           'Allowance' user.allowance,
           'Total Holidays in Calendar' user.totalHolidaysInCal,
           'Holidays Booked' user.numHolidaysBooked,
           'Holidays Taken' user.numHolidaysTaken,
           'Holidays Remaining' user.totalHolidaysLeft,
           'Holidays' user.holidayEvents.collect{ evt ->
               [
                  'Start Date': evt.startDate,
                  'End Date': evt.endDate,
                  'Days': evt.days
               ]
            }
        }

But this returned all the keys except the Holidays key.

Any help would be greatly appreciated!

EDIT - My code now looks like this:

public String buildOneUser(DyveUserDTO user)
{
    def userBuilder = new JsonBuilder()
        userBuilder user.collect { usr ->
            [
                    'Name': usr.userName,
                    'Allowance': usr.allowance,
                    'Total Holidays in Calendar': usr.totalHolidaysInCal,
                    'Holidays Booked': usr.numHolidaysBooked,
                    'Holidays Taken': usr.numHolidaysTaken,
                    'Holidays Remaining': usr.totalHolidaysLeft,
                    'Holidays': usr.holidayEvents.collect{ evt ->
                        [
                                'Start Date': evt.startDate,
                                'End Date': evt.endDate,
                                'Days': evt.days
                        ]
                    }
            ]
        }
}

EDIT 2 - Sample Code

Method to call:

public String buildOneUser(DyveUserDTO user)
{
    def userBuilder = new JsonBuilder()
    userBuilder {
        Name:
        user.userName
        Allowance:
        user.allowance
        TotalHolidaysInCalendar:
        user.totalHolidaysInCal
        HolidaysBooked:
        user.numHolidaysBooked
        HolidaysTaken:
        user.numHolidaysTaken
        HolidaysRemaining:
        user.totalHolidaysLeft
        Holidays:
        user.holidayEvents.collect { evt ->
            [
                    'Start Date': evt.startDate,
                    'End Date'  : evt.endDate,
                    'Days'      : evt.days
            ]
        }
    }

    return userBuilder.toPrettyString()
}

User to pass in:

class DyveUserDTO
{
    String firstName = "Foo"
    String userName = "FooBar"
    Integer userID = 42
    BigDecimal numHolidaysBooked = 3
    BigDecimal numHolidaysTaken = 0
    BigDecimal totalHolidaysInCal = 3
    BigDecimal totalHolidaysLeft = 12
    BigDecimal allowance = 12
    List<HolidayObject> holidayEvents = []

}

Holiday objects to go in holidayEvents:

class HolidayObject
{
    public Integer userID = 42
    public String title = "Foo Holiday"
    public String event = "Holiday"
    public String amPm = "Full Day"
    public String name = "Foo"
    public LocalDateTime startDate = LocalDateTime.parse(2015-02-20T00:00:00)
    public LocalDateTime endDate = LocalDateTime.parse(2015-02-20T00:00:00)
    public BigDecimal days = 1
}

class HolidayObject
{
    public Integer userID = 42
    public String title = "Foo Holiday Pm"
    public String event = "Holiday"
    public String amPm = "Pm"
    public String name = "Foo"
    public LocalDateTime startDate = LocalDateTime.parse(2015-02-23T00:00:00)
    public LocalDateTime endDate = LocalDateTime.parse(2015-02-24T00:00:00)
    public BigDecimal days = 2
}

Solution

  • each just returns the list it's called upon, collect should be used for events. See the working code below:

    import groovy.json.JsonBuilder
    
    class UserEvent {
        def start
        def end
        def days
    }
    
    class User {
        def name
        def events
    }
    
    def u1 = new User(name: 'u1', events: [new UserEvent(start: 0, end: 1, days: 1), new UserEvent(start: 0, end: 2, days: 2)])
    def u2 = new User(name: 'u2', events: [new UserEvent(start: 0, end: 3, days: 3)])
    
    def users = [u1, u2]
    
    def userBuilder = new JsonBuilder()
    userBuilder users.collect { usr ->
       [
          'name': usr.name,   
          'events': usr.events.collect { e ->
             [
                start: e.start,
                end: e.end,
                days: e.days,
             ]
           }                   
        ]
    }
    
    print  userBuilder.toPrettyString()
    

    EDIT

    Below is a working example:

    import groovy.json.JsonBuilder
    
    user = new DyveUserDTO()
    
    def userBuilder = new JsonBuilder()
        userBuilder {
            Name user.userName
            Allowance user.allowance
            TotalHolidaysInCalendar user.totalHolidaysInCal
            HolidaysBooked user.numHolidaysBooked
            HolidaysTaken user.numHolidaysTaken
            HolidaysRemaining user.totalHolidaysLeft
            Holidays user.holidayEvents.collect { evt ->
                [
                        'Start Date': evt.startDate,
                        'End Date'  : evt.endDate,
                        'Days'      : evt.days
                ]
            }
        }
    
    println userBuilder.toPrettyString()
    
    class DyveUserDTO {
        String firstName = "Foo"
        String userName = "FooBar"
        Integer userID = 42
        BigDecimal numHolidaysBooked = 3
        BigDecimal numHolidaysTaken = 0
        BigDecimal totalHolidaysInCal = 3
        BigDecimal totalHolidaysLeft = 12
        BigDecimal allowance = 12
        List<HolidayObject> holidayEvents = [new HolidayObject(), new HolidayObject()]
    }
    
    class HolidayObject {
        public Integer userID = 42
        public String title = "Foo Holiday"
        public String event = "Holiday"
        public String amPm = "Full Day"
        public String name = "Foo"
        public String startDate = '2015-02-20T00:00:00'
        public String endDate = '2015-02-20T00:00:00'
        public BigDecimal days = 1
    }
    

    No colons : needed. See the sample here. Also I have no Joda dependency so replaced with String.