{"action":"created","issue":{"url":"https://api.github.com/repos/spring-projects/spring-boot/issues/4027","labels_url":"https://api.github.com/repos/spring-projects/spring-boot/issues/4027/labels{/name}","comments_url":"https://api.github.com/repos/spring-projects/spring-boot/issues/4027/comments","events_url":"https://api.github.com/repos/spring-projects/spring-boot/issues/4027/events","html_url":"https://github.com/spring-projects/spring-boot/issues/4027","id":108379881,"number":4027,"title":"Using JSON instead of Properties","user":{"login":"marcellodesales","id":131457,"avatar_url":"https://avatars.githubusercontent.com/u/131457?v=3","gravatar_id":"","url":"https://api.github.com/users/marcellodesales","html_url":"https://github.com/marcellodesales","followers_url":"https://api.github.com/users/marcellodesales/followers","following_url":"https://api.github.com/users/marcellodesales/following{/other_user}","gists_url":"https://api.github.com/users/marcellodesales/gists{/gist_id}","starred_url":"https://api.github.com/users/marcellodesales/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/marcellodesales/subscriptions","organizations_url":"https://api.github.com/users/marcellodesales/orgs","repos_url":"https://api.github.com/users/marcellodesales/repos","events_url":"https://api.github.com/users/marcellodesales/events{/privacy}","received_events_url":"https://api.github.com/users/marcellodesales/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/spring-projects/spring-boot/labels/waiting-for-votes","name":"waiting-for-votes","color":"fef2c0"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":9,"created_at":"2015-09-25T18:07:36Z","updated_at":"2015-10-01T08:00:33Z","closed_at":null,"body":"Hi there,\r\n\r\nI have a requirement to share configuration between backend and frontend layers of applications using JSON format. That way, the front-end can load and use JSON directly.\r\n\r\nI need the backend services to support loading properties from JSON as it is done with YAML http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html#boot-features-external-config-yaml.\r\n\r\nIs there a quick way to support storing configuration using JSON instead of YAML and properties files?\r\n\r\nthanks\r\nMarcello"},"comment":{"url":"https://api.github.com/repos/spring-projects/spring-boot/issues/comments/144649875","html_url":"https://github.com/spring-projects/spring-boot/issues/4027#issuecomment-144649875","issue_url":"https://api.github.com/repos/spring-projects/spring-boot/issues/4027","id":144649875,"user":{"login":"marcellodesales","id":131457,"avatar_url":"https://avatars.githubusercontent.com/u/131457?v=3","gravatar_id":"","url":"https://api.github.com/users/marcellodesales","html_url":"https://github.com/marcellodesales","followers_url":"https://api.github.com/users/marcellodesales/followers","following_url":"https://api.github.com/users/marcellodesales/following{/other_user}","gists_url":"https://api.github.com/users/marcellodesales/gists{/gist_id}","starred_url":"https://api.github.com/users/marcellodesales/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/marcellodesales/subscriptions","organizations_url":"https://api.github.com/users/marcellodesales/orgs","repos_url":"https://api.github.com/users/marcellodesales/repos","events_url":"https://api.github.com/users/marcellodesales/events{/privacy}","received_events_url":"https://api.github.com/users/marcellodesales/received_events","type":"User","site_admin":false},"created_at":"2015-10-01T08:00:33Z","updated_at":"2015-10-01T08:00:33Z","body":"@philwebb I greatly appreciate your reply... I've been super busy this week the last 40hrs :S and I hadn't got back to this... \r\n\r\nYes, I have the following code in place:\r\n\r\npom.xml Dependency\r\n-----\r\n\r\nFor loading JSON.\r\n\r\n```xml\r\n            <dependency>\r\n                   <groupId>com.fasterxml.jackson.core</groupId>\r\n                   <artifactId>jackson-core</artifactId>\r\n                   <optional>true</optional>\r\n             </dependency>\r\n```\r\n\r\nJsonPropertiesLoader\r\n-------\r\n\r\nThere are a lot of restrictions in this version:\r\n\r\n* Json documents do not have the notion of multiple documents.\r\n * We can have a convention over the environments/profiles, but I think that's not the case.\r\n* I copied code from the YAMLProcessor :) But it follows the same structure for JSON. If the copied method were a utility, I would not need to do so.\r\n\r\n```java\r\n/*\r\n * Copyright 2012-2015 the original author or authors.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n *      http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\n\r\npackage org.springframework.boot.env;\r\n\r\nimport java.io.IOException;\r\nimport java.util.Collection;\r\nimport java.util.Collections;\r\nimport java.util.LinkedHashMap;\r\nimport java.util.Map;\r\nimport java.util.Map.Entry;\r\n\r\nimport org.springframework.beans.factory.config.YamlProcessor;\r\nimport org.springframework.beans.factory.config.YamlPropertiesFactoryBean;\r\nimport org.springframework.core.env.MapPropertySource;\r\nimport org.springframework.core.env.PropertySource;\r\nimport org.springframework.core.io.Resource;\r\nimport org.springframework.util.ClassUtils;\r\nimport org.springframework.util.StringUtils;\r\n\r\nimport com.fasterxml.jackson.databind.ObjectMapper;\r\n\r\n/**\r\n * Strategy to load '.json' files into a {@link PropertySource}.\r\n *\r\n * @author Marcello de Sales\r\n */\r\npublic class JsonPropertySourceLoader implements PropertySourceLoader {\r\n\r\n\t@Override\r\n\tpublic String[] getFileExtensions() {\r\n\t\treturn new String[] { \"json\" };\r\n\t}\r\n\r\n\t@Override\r\n\tpublic PropertySource<?> load(String name, Resource resource, String profile)\r\n\t\t\tthrows IOException {\r\n\t\tif (ClassUtils.isPresent(\"com.fasterxml.jackson.databind.ObjectMapper\", null)) {\r\n\t\t\tProcessor processor = new Processor(resource, profile);\r\n\t\t\tMap<String, Object> source = processor.process();\r\n\t\t\tif (!source.isEmpty()) {\r\n\t\t\t\treturn new MapPropertySource(name, source);\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn null;\r\n\t}\r\n\r\n\t/**\r\n\t * {@link YamlProcessor} to create a {@link Map} containing the property values.\r\n\t * Similar to {@link YamlPropertiesFactoryBean} but retains the order of entries.\r\n\t */\r\n\tprivate static class Processor {\r\n\r\n\t\tprivate Resource resource;\r\n\r\n\t\tProcessor(Resource resource, String profile) {\r\n\t\t\tthis.resource = resource;\r\n\t\t}\r\n\r\n\t\t@SuppressWarnings(\"unchecked\")\r\n\t\tpublic Map<String, Object> process() {\r\n\t\t\tfinal Map<String, Object> result = new LinkedHashMap<String, Object>();\r\n\t\t\tMap<String, Object> map;\r\n\t\t\ttry {\r\n\t\t\t\tmap = new ObjectMapper().readValue(this.resource.getFile(), LinkedHashMap.class);\r\n\t\t\t\tresult.putAll(getFlattenedMap(map));\r\n\r\n\t\t\t} catch (Exception e) {\r\n\t\t\t\te.printStackTrace();\r\n\t\t\t}\r\n\t\t\treturn result;\r\n\t\t}\r\n\r\n\t\t/**\r\n\t\t * Copied from\r\n\t\t * https://github.com/spring-projects/spring-framework/blob/master/spring-beans/\r\n\t\t * src/ main/java/org/springframework/beans/factory/config/YamlProcessor.java\r\n\t\t * @param source\r\n\t\t * @return Flattened map of the key.subkey=value\r\n\t\t */\r\n\t\tprivate final Map<String, Object> getFlattenedMap(Map<String, Object> source) {\r\n\t\t\tMap<String, Object> result = new LinkedHashMap<String, Object>();\r\n\t\t\tbuildFlattenedMap(result, source, null);\r\n\t\t\treturn result;\r\n\t\t}\r\n\r\n\t\tprivate void buildFlattenedMap(Map<String, Object> result,\r\n\t\t\t\tMap<String, Object> source, String path) {\r\n\t\t\tfor (Entry<String, Object> entry : source.entrySet()) {\r\n\t\t\t\tString key = entry.getKey();\r\n\t\t\t\tif (StringUtils.hasText(path)) {\r\n\t\t\t\t\tif (key.startsWith(\"[\")) {\r\n\t\t\t\t\t\tkey = path + key;\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tkey = path + \".\" + key;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tObject value = entry.getValue();\r\n\t\t\t\tif (value instanceof String) {\r\n\t\t\t\t\tresult.put(key, value);\r\n\r\n\t\t\t\t} else if (value instanceof Map) {\r\n\t\t\t\t\t// Need a compound key\r\n\t\t\t\t\t@SuppressWarnings(\"unchecked\")\r\n\t\t\t\t\tMap<String, Object> map = (Map<String, Object>) value;\r\n\t\t\t\t\tbuildFlattenedMap(result, map, key);\r\n\r\n\t\t\t\t} else if (value instanceof Collection) {\r\n\t\t\t\t\t// Need a compound key\r\n\t\t\t\t\t@SuppressWarnings(\"unchecked\")\r\n\t\t\t\t\tCollection<Object> collection = (Collection<Object>) value;\r\n\t\t\t\t\tint count = 0;\r\n\t\t\t\t\tfor (Object object : collection) {\r\n\t\t\t\t\t\tbuildFlattenedMap(result,\r\n\t\t\t\t\t\t\t\tCollections.singletonMap(\"[\" + (count++) + \"]\", object),\r\n\t\t\t\t\t\t\t\tkey);\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} else {\r\n\t\t\t\t\tresult.put(key, value == null ? \"\" : value);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n```\r\n\r\nThanks a lot for clarifying and providing the steps above... I will try to follow them by Friday and then I can provide more feedback... \r\n\r\nAs Intuit is hosting a Spring Cloud Config connected with out GitHub Enterprise, this will bring a lot of value to the Node.js internal Community. Thanks a lot for listening!"}}