I have yaml:
- flowId: "2021:6:10:20:22:7" flowType: "BIG" summary: "Description" flowStatus: "NEW" createdDate: "2021-06-10" lastModifiedDate: "2021-06-10" class Flow{ ... FlowType flowType; ... } Enum FlowType{ SMALL,MEDIUM, BIG; }
Parsing file using YamlSlurper:
def flowList = new YamlSlurper().parseText(new File(myFile).text).collect { it as Flow }
error: java.lang.ClassCastException: java.lang.String cannot be cast to model.FlowType
Is there a way to solve this?
Advertisement
Answer
The YAML slurper is a cute tool to quickly read a YAML file or string and deal with it to the degree, that you would use the other slurpers: get some basic data types inside lists and maps and just use that.
Your attempt to cast the map to the object only works for very basic objects. The cast basically gets unrolled to something like:
[a: 42] as X
becomes
def x = new X() map.each{ k, v -> x."$k" = v }
This does:
- not coerce/convert types
- fails if keys in the map, that are not set-able properties in the resulting object
If you need proper object mapping, the slurpers are not directly useful most of the time. You would rather switch to using something made for that task — e.g. like Jackson.
Lucky for us, the YAML slurper just uses Jackson (it actually just transforms the YAML into JSON and then uses the JSON slurper to give you your data back).
Following an example of how to load the YAML data into objects using
Jackson (all deps are already there, if you already see YamlSlurper
):
import com.fasterxml.jackson.core.type.TypeReference import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.databind.DeserializationFeature import com.fasterxml.jackson.dataformat.yaml.YAMLFactory import com.fasterxml.jackson.dataformat.yaml.YAMLMapper def yamlStr = """ - flowId: "2021:6:10:20:22:7" flowType: "BIG" summary: "Description" flowStatus: "NEW" createdDate: "2021-06-10" lastModifiedDate: "2021-06-10" """ enum FlowType{ SMALL,MEDIUM, BIG } @groovy.transform.ToString class Flow { FlowType flowType } def flows = new ObjectMapper(new YAMLFactory()).with{ configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) readValue(yamlStr, new TypeReference<List<Flow>>(){}) } println flows // → Flow(BIG)