Groovy - How to convert json to a list of exact types
Asked Answered
M

2

6

I come from Java background and am new to Groovy-Spock testing. I need to convert a list in Json to a List. I cannot share the exact code (proprietary), but here is in essence what is going on.

emp_test_data.json

[{
    "empID":"1234",
    "location":"HQ"
  },
  {
    "empID":"5678",
    "location":"Warehouse"
}]

Groovy code

List<Employee> employeeList = slurper.parse(new File("src/test/resources/data/emp_test_data.json"))

println ("After slurped")  //prints
println(pickupVOList.size()  //prints 2
println(pickupVOList.get(0))  //prints [empID:5678, location:HQ]

empUtil.processEmployees(employeeList)

EmpUtil.java

public void processEmployees(List<Employee> employeeList) {
    for (Employee employee: employeeList) { //THIS FAILS!
        //Do some processing
    }
    return;
}

The error I get is:- java.lang.ClassCastException: groovy.json.internal.LazyMap cannot be cast to com.my.domain.Employee

I've looked around quite a bit. In Groovy, there must be the right way of converting json to List of exact objects, not a list of LazyMap, but I cannot seem to find it.

Any ideas?

Moultrie answered 27/11, 2018 at 21:17 Comment(1)
Unless your Employee has the same fields like the JSON (then you can can use the map c'tor) or you map yourself: you have to use a third party mapping or data binding tool like Jackson or anything else what hte java universe has to offer.Philip
Y
7

There is no deserialization to POJO feature in Groovy's JsonSlurper class. However, you can transform a list of LazyMap entries into a list of Employee objects. I don't know what your Employee class exactly looks like, but let's assume it has only these two fields and there is a single constructor that accepts two parameters - empID and location.

File file = new File("src/test/resources/data/emp_test_data.json")
List<Employee> employeeList = slurper.parse(file).collect {
    new Employee(it.empID, it.location)
}

In case your Employee class follows POJO conventions (default non-parameter constructor, setters/getters), then you might do something like this:

File file = new File("src/test/resources/data/emp_test_data.json")
List<Employee> employeeList = slurper.parse(file).collect {
    def emp = new Employee()
    emp.empID = it.empID
    emp.location = it.location
    return emp
}

Or even extract transformation part to a closure to make code even more readable:

Closure asEmployee = { Map map ->
    def emp = new Employee()
    emp.empID = map.empID
    emp.location = map.location
    return emp
}
File file = new File("src/test/resources/data/emp_test_data.json")
List<Employee> employeeList = slurper.parse(file).collect(asEmployee)

Now your Java code should be satisfied with the correct static type.

Yseulte answered 27/11, 2018 at 21:34 Comment(2)
+1. Thanks. This works! However, if the number of fields in a POJO is large - as many enterprise domain objects can be with embedded field, this can get unwieldy, right? Doesn't Groovy provide a way to convert JSON string to a List of Objects?Moultrie
@Moultrie As cfrick mentioned in the comment above, deserializing/serializing between JSON and Groovy/Java classes can be done by using 3rd party libraries like the mentioned Jackson databinder. Groovy in this field does not offer much more than Java. The only difference is Map constructor that Groovy adds to Groovy (not Java) classes. In this case you could pass a whole LazyMap to Employee constructor and Groovy would match keys with specific fields in your class.Yseulte
U
0

What about:

List<Employee> employeeList = new JsonSlurper().parse(file).collect(it as Employee)

This code (based on the page baeldung.com/groovy-json) gave me an output of List<Acc>:

def jsonSlurper = new JsonSlurper(type: JsonParserType.INDEX_OVERLAY)
def parsedList = jsonSlurper.parseText('[
    {"id":"123","createdAt":"2018-01-01T02:00:00+0000"}, 
    {"id":"124","createdAt":"2018-01-01T02:00:00+0000"}
    ]')
def objectList = parsedList.collect {it as Acc}
Uraninite answered 2/10, 2020 at 10:24 Comment(1)
This answer is incomplete since there is no info what Acc is.Intercessory

© 2022 - 2024 — McMap. All rights reserved.