java properties to json

46,235

Solution 1

Not the easy way, but I managed to do that using Gson library. The result will be in the jsonBundle String. Here we getting the properties or bundles in this case:

final ResourceBundle bundle = ResourceBundle.getBundle("messages");
final Map<String, String> bundleMap = resourceBundleToMap(bundle);

final Type mapType = new TypeToken<Map<String, String>>(){}.getType();

final String jsonBundle = new GsonBuilder()
        .registerTypeAdapter(mapType, new BundleMapSerializer())
        .create()
        .toJson(bundleMap, mapType);

For this implementation ResourceBundle have to be converted to Map containing String as a key and String as a value.

private static Map<String, String> resourceBundleToMap(final ResourceBundle bundle) {
    final Map<String, String> bundleMap = new HashMap<>();

    for (String key: bundle.keySet()) {
        final String value = bundle.getString(key);

        bundleMap.put(key, value);
    }

    return bundleMap;
}

I had to create custom JSONSerializer using Gson for Map<String, String>:

public class BundleMapSerializer implements JsonSerializer<Map<String, String>> {

    private static final Logger LOGGER = LoggerFactory.getLogger(BundleMapSerializer.class);

    @Override
    public JsonElement serialize(final Map<String, String> bundleMap, final Type typeOfSrc, final JsonSerializationContext context) {
        final JsonObject resultJson =  new JsonObject();

        for (final String key: bundleMap.keySet()) {
            try {
                createFromBundleKey(resultJson, key, bundleMap.get(key));
            } catch (final IOException e) {
                LOGGER.error("Bundle map serialization exception: ", e);
            }
        }

        return resultJson;
    }
}

And here is the main logic of creating JSON:

public static JsonObject createFromBundleKey(final JsonObject resultJson, final String key, final String value) throws IOException {
    if (!key.contains(".")) {
        resultJson.addProperty(key, value);

        return resultJson;
    }

    final String currentKey = firstKey(key);
    if (currentKey != null) {
        final String subRightKey = key.substring(currentKey.length() + 1, key.length());
        final JsonObject childJson = getJsonIfExists(resultJson, currentKey);

        resultJson.add(currentKey, createFromBundleKey(childJson, subRightKey, value));
    }

    return resultJson;
}

    private static String firstKey(final String fullKey) {
        final String[] splittedKey = fullKey.split("\\.");

        return (splittedKey.length != 0) ? splittedKey[0] : fullKey;
    }

    private static JsonObject getJsonIfExists(final JsonObject parent, final String key) {
        if (parent == null) {
            LOGGER.warn("Parent json parameter is null!");
            return null;
        }

        if (parent.get(key) != null && !(parent.get(key) instanceof JsonObject)) {
            throw new IllegalArgumentException("Invalid key \'" + key + "\' for parent: " + parent + "\nKey can not be JSON object and property or array in one time");
        }

        if (parent.getAsJsonObject(key) != null) {
            return parent.getAsJsonObject(key);
        } else {
            return new JsonObject();
        }
   }

In the end, if there were a key person.name.firstname with value John, it will be converted to such JSON:

{
     "person" : {
         "name" : {
             "firstname" : "John"
         }
     }
}

Hope this will help :)

Solution 2

Using lightbend config java library (https://github.com/lightbend/config)

String toHierarchicalJsonString(Properties props) {
  com.typesafe.config.Config config = com.typesafe.config.ConfigFactory.parseProperties(props);
  return config.root().render(com.typesafe.config.ConfigRenderOptions.concise());
}

Solution 3

It is pretty easy, download and add to your lib: https://code.google.com/p/google-gson/

Gson gsonObj = new Gson();
String strJson =  gsonObj.toJson(yourObject);

Solution 4

You can try with https://github.com/mikolajmitura/java-properties-to-json

You can generate Json from:

  • from Java properties (java.util.Properties)
  • from Map (import java.util.Map) -> Map<String,String>
  • from Map (import java.util.Map) -> Map<String,Object>
  • from InputStream with properties (java.io.InputStream)
  • from given file localization with properties
  • from File with properties (java.io.File)


code example:

import pl.jalokim.propertiestojson.util.PropertiesToJsonConverter;

...

Properties properties = ....;
String jsonFromProperties = new PropertiesToJsonConverter().convertToJson(properties);

InputStream inputStream = ....;
String jsonFromInputStream = new PropertiesToJsonConverter().convertToJson(inputStream);

Map<String,String> mapProperties = ....;
String jsonFromInputProperties = new PropertiesToJsonConverter().convertToJson(mapProperties);

Map<String, Object> valuesAsObjectMap = ....;
String jsonFromProperties2 = new PropertiesToJsonConverter().convertFromValuesAsObjectMap(valuesAsObjectMap);

String jsonFromFilePath = new PropertiesToJsonConverter().convertPropertiesFromFileToJson("/home/user/file.properties");

String jsonFromFile = new PropertiesToJsonConverter().convertPropertiesFromFileToJson(new File("/home/user/file.properties"));

maven dependency:

      <dependency>
          <groupId>pl.jalokim.propertiestojson</groupId>
          <artifactId>java-properties-to-json</artifactId>
          <version>5.1.0</version>
      </dependency>

dependency required minimum java 8.

more example of uses on https://github.com/mikolajmitura/java-properties-to-json

Solution 5

I didn't want any dependency on gson and I wanted to return a hierarchical json from a Spring controller so a deep Map was enough for me.

This works for me, just loop over all your keys and pass in an empty map.

void recurseCreateMaps(Map<String, Object> currentMap, String key, String value) {
    if (key.contains(".")) {
        String currentKey = key.split("\\.")[0];

        Map<String, Object> deeperMap;

        if (currentMap.get(currentKey) instanceof Map) {
            deeperMap = (Map<String, Object>) currentMap.get(currentKey);
        } else {
            deeperMap = new HashMap<>();
            currentMap.put(currentKey, deeperMap);
        }

        recurseCreateMaps(deeperMap, key.substring(key.indexOf('.') + 1), value);
    } else {
        currentMap.put(key, value);
    }
}
Share:
46,235
Vitali Bichov
Author by

Vitali Bichov

Updated on August 11, 2020

Comments

  • Vitali Bichov
    Vitali Bichov over 3 years

    Is there an easy way to convert properties with dot notation to json

    I.E

    server.host=foo.bar
    server.port=1234
    

    TO

    {
     "server": {
        "host": "foo.bar",
        "port": 1234
      }
    } 
    
  • Ostap Maliuvanchuk
    Ostap Maliuvanchuk almost 10 years
    The guy need to convert properties to JSON. Not just read json from file to JsonObject.
  • Vitali Bichov
    Vitali Bichov almost 10 years
    the result is: {"server.host":"foo.bar","server.port":1234} but I want to created a hierarchical json
  • Vitali Bichov
    Vitali Bichov almost 10 years
    Again, this converts properties to flat json, I'm looking for something that creates hierarchical json
  • Rocky Hu
    Rocky Hu over 9 years
    Hi, Yuriy, I used Gjson2.3 and have the exception Exception in thread "main" java.lang.ClassCastException: com.google.gson.JsonPrimitive cannot be cast to com.google.gson.JsonObject at com.google.gson.JsonObject.getAsJsonObject(JsonObject.java:1‌​82) at tools.BundleMapSerializer.getJsonIfExists(BundleMapSerialize‌​r.java:67)
  • yyunikov
    yyunikov over 9 years
    The problem is that the object in properties can not be the primitive and JSON object at the same time, so you need to avoid key duplicates like: key.name.a=something, key.name=something2
  • Rocky Hu
    Rocky Hu over 9 years
    yes, you are right, I found my problem, just like you said
  • Martijn Pieters
    Martijn Pieters almost 8 years
    You may want to read How to offer personal open-source libraries? before posting about your project some more.
  • abdelrahman-sinno
    abdelrahman-sinno about 7 years
    I really need this for java 7 !
  • xman_bsn
    xman_bsn about 4 years
    Hi Martijn, just wondering how to keep the original order of properties file elements by using PropertiesToJsonConverter().convertPropertiesFromFileToJson(‌​)? This method always returns JSON content in a descending order. Would that be configurable? Many thanks!
  • Mikołaj Mitura
    Mikołaj Mitura about 4 years
    @xman_bsn this is not configurable, real key properties order is lost by "properties.load(inputStream);" under the hood. but at this moment you can do you implementation of PropertyKeysOrderResolver code below: PropertiesToJsonConverter converter = new PropertiesToJsonConverter(); converter.setPropertyKeysOrderResolver(new PropertyKeysOrderResolver() { public List<String> getKeysInExpectedOrder(Map<String, ?> properties) { // TODO implement way how you want gather properties key order } });
  • Mikołaj Mitura
    Mikołaj Mitura almost 4 years
    from 5.1.3 version order of properties in json structure is the same like in the properties file. Converting from Map or Properties class directly order of properties will not be kept.