Skip to content

YamlPropertiesFactoryBean incorrect flatten nested map to properties when map key contains escaped brackets #27020

Open
@ian4hu

Description

@ian4hu

Affects: since 4.1


Yaml file like bellow:

root:
  webservices:
    "[domain.test:8080]":
      - username: me
        password: mypassword

Yaml's map to json like

{
   "webservices": {
      "[domain.test:8080]": [
         {
            "username": "me",
            "password": "mypassword"
         }
      ]
   }
}

should equals properties file like:

root.webservices.[[domain.test\:8080]][0].username=me
root.webservices.[[domain.test\:8080]][0].password=mypassword

or:

root.webservices[[domain.test\:8080]][0].username=me
root.webservices[[domain.test\:8080]][0].password=mypassword

Both properties file is acceptable for Spring Boot Binding Maps

Reproduce Test Case is

	@Test
	void loadNestedEscapedProperties() throws Exception {

		String yaml = "root:\n" +
				"  webservices:\n" +
				"    \"[domain.test:8080]\":\n" +
				"      - username: me\n" +
				"        password: mypassword\n";
		String propsStr = "root.webservices[[domain.test\\:8080]][0].username=me\n" +
				"root.webservices[[domain.test\\:8080]][0].password=mypassword";
		final PropertiesFactoryBean factory = new PropertiesFactoryBean();
		factory.setLocations(new ByteArrayResource(propsStr.getBytes(StandardCharsets.UTF_8)));
		factory.setSingleton(false);
		final Properties properties = factory.getObject();

		final YamlPropertiesFactoryBean yamlFactory = new YamlPropertiesFactoryBean();
		yamlFactory.setResources(new ByteArrayResource(yaml.getBytes(StandardCharsets.UTF_8)));
		assertThat(yamlFactory.getObject()).isEqualTo(properties);
	}

Current it is failed like bellow

expected: {"root.webservices[[domain.test:8080]][0].password"="mypassword", "root.webservices[[domain.test:8080]][0].username"="me"}
but was : {"root.webservices[domain.test:8080][0].password"="mypassword", "root.webservices[domain.test:8080][0].username"="me"}
org.opentest4j.AssertionFailedError: 
expected: {"root.webservices[[domain.test:8080]][0].password"="mypassword", "root.webservices[[domain.test:8080]][0].username"="me"}
but was : {"root.webservices[domain.test:8080][0].password"="mypassword", "root.webservices[domain.test:8080][0].username"="me"}
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at org.springframework.beans.factory.config.YamlPropertiesFactoryBeanTests.loadNestedEscapedProperties(YamlPropertiesFactoryBeanTests.java:270)

It seems there is a bug cause yaml's nested map is flatten incorrectly like

root.webservices[domain.test:8080][0].username=me
root.webservices[domain.test:8080][0].password=mypassword

Metadata

Metadata

Assignees

No one assigned

    Labels

    in: coreIssues in core modules (aop, beans, core, context, expression)type: bugA general bug

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions