Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Load spring-boot properties from json file

Is it possible to load spring-boot config from a .json file as opposed to .yaml or .properties? From looking at the documentation, this isn't supported out of the box - I'm wondering if it's possible and if so how one would go about doing it?

like image 662
Andy W Avatar asked Jun 15 '17 09:06

Andy W


People also ask

How does Spring load properties file?

properties file in the src/main/resources directory, and then set a Spring profile with the same environment name. For example, if we define a “staging” environment, that means we'll have to define a staging profile and then application-staging.

How do you get a specific value from a JSON string?

getJsonString() Method It is used to get the (JsonString)get(name). The method parses an argument name of type String whose related value is to be returned. It returns the String value of the associated mapping for the parsed parameter. It returns null if the object has no mapping for the parameter.


3 Answers

As noted in docs and on GitHub

YAML is a superset of JSON

So you can just create the following class in your Spring Boot project:

public class JsonPropertySourceLoader extends YamlPropertySourceLoader {
    @Override
    public String[] getFileExtensions() {
        return new String[]{"json"};
    }
}

Then create a file:

/src/main/resources/META-INF/spring.factories with the following content:

org.springframework.boot.env.PropertySourceLoader=\
io.myapp.JsonPropertySourceLoader

And your Spring application is ready to load JSON configurations from application.json. The priority will be: .properties -> .yaml -> .json

If you have multiple apps, you can create a jar with the shared PropertySourceLoader and spring.factories file in order to include it to any project you need.

like image 84
Kirill Avatar answered Sep 22 '22 16:09

Kirill


The spring boot way:

@EnableAutoConfiguration
@Configuration
@PropertySource(value = { "classpath:/properties/config.default.json" }, factory=SpringBootTest.JsonLoader.class )
public class SpringBootTest extends SpringBootServletInitializer {

    @Bean
    public Object test(Environment e) {
        System.out.println(e.getProperty("test"));
        return new Object();
    }


    public static void main(String[] args) {
        SpringApplication.run(SpringBootTest.class);
    }

    public static class JsonLoader implements PropertySourceFactory {

        @Override
        public org.springframework.core.env.PropertySource<?> createPropertySource(String name,
                EncodedResource resource) throws IOException {
            Map readValue = new ObjectMapper().readValue(resource.getInputStream(), Map.class);
            return new MapPropertySource("json-source", readValue);
        }

    }
}

Define your own PropertySourceFactory and hook it in via the @PropertySource annotation. Read the resource, set the properties, use them anywhere.

Only thing is, how do you translate nested properties. The Spring way to do that (by the way you can define Json also as a variable for properties, see: https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html) is to translate nested properties as such:

{"test": { "test2" : "x" } }

Becomes:

test.test2.x

Hope that helps,

Artur

like image 29
pandaadb Avatar answered Sep 18 '22 16:09

pandaadb


The SPRING_APPLICATION_JSON properties can be supplied on the command line with an environment variable. For example, you could use the following line in a UN*X shell:

$ SPRING_APPLICATION_JSON='{"acme":{"name":"test"}}' java -jar myapp.jar

In the preceding example, you end up with acme.name=test in the Spring Environment. You can also supply the JSON as spring.application.json in a System property, as shown in the following example:

$ java -Dspring.application.json='{"name":"test"}' -jar myapp.jar

You can also supply the JSON by using a command line argument, as shown in the following example:

$ java -jar myapp.jar --spring.application.json='{"name":"test"}'

You can also supply the JSON as a JNDI variable, as follows:

java:comp/env/spring.application.json.

Reference documentation: https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html

like image 43
Ashu Avatar answered Sep 19 '22 16:09

Ashu