We have a configuration of list of objects

elastic:
  mappings:
    dynamic_templates:
    - longs_as_strings:
        match_mapping_type: string
        match: long_*
        unmatch: "*_text"
        mapping:
          type: long

This is mapped to

@Configuration
@ConfigurationProperties(prefix = "elastic")
public class ElasticProperties {
    private Map<String, ?> mappings;
    // ...
}

When we verify the type of dynamic_templates value, it is HashMap, however in the yaml we declared that it is a list, and Elasticsearch client expects a List. Is it expected behavior?

Comment From: wilkinsona

The following properties are created from the YAML:

  • elastic.mappings.dynamic_templates[0].longs_as_strings.match_mapping_type=string
  • elastic.mappings.dynamic_templates[0].longs_as_strings.match=long_*
  • elastic.mappings.dynamic_templates[0].longs_as_strings.unmatch=*_text
  • elastic.mappings.dynamic_templates[0].longs_as_strings.mapping.type=long

This results in the following structure in ElasticProperties:

 "mappings": {
    "dynamic_templates": {
        "0": {
            "longs_as_strings": {
                "mapping": {
                    "type": "long"
                },
                "match": "long_*",
                "match_mapping_type": "string",
                "unmatch": "*_text"
            }
        }
    }
}

In the absence of any type information in ElasticProperties, I wonder if we can infer from the [n] in the property name that dynamic_templates should be a list?

Comment From: raderio

It should be

"mappings": {
    "dynamic_templates": [
            "longs_as_strings": {
                "mapping": {
                    "type": "long"
                },
                "match": "long_*",
                "match_mapping_type": "string",
                "unmatch": "*_text"
            }
        }
    ]
}

As we declared in yaml that it is a list

Comment From: philwebb

I wonder if we can infer from the [n] in the property name that dynamic_templates should be a list

We currently always drive binding from the type information that we have in the class. I don't think we should attempt to change things based on the contents of the properties file.

Taking a step back, the Binder is really designed to work with strongly typed objects. In the small snippet that you provide you have mappings as a Map<String, ?>. Is there any reason why you can't provide a complete generic signature? Something like Map<String, List<Details>>. If not, then I'm afraid the Binder really isn't designed for your use-case. You'll probably need to work with SnakeYaml directly.

Comment From: raderio

I cannot use Map<String, List<Details>> as values in the map are not always lists