private static JsonElement dumpConfig(Table<String, String, IConfigPropertyHolder> properties) {
    JsonObject result = new JsonObject();

    Gson gson =
        new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().serializeNulls().create();

    for (Map.Entry<String, Map<String, IConfigPropertyHolder>> category :
        properties.rowMap().entrySet()) {
      JsonObject categoryNode = new JsonObject();

      for (Map.Entry<String, IConfigPropertyHolder> property : category.getValue().entrySet()) {
        JsonObject propertyNode = new JsonObject();

        IConfigPropertyHolder propertyHolder = property.getValue();

        final String comment = propertyHolder.comment();
        if (!Strings.isNullOrEmpty(comment)) propertyNode.addProperty(COMMENT_TAG, comment);

        try {
          Object value = propertyHolder.getValue();
          JsonElement serialized = gson.toJsonTree(value);
          propertyNode.add(VALUE_TAG, serialized);
        } catch (Exception e) {
          Log.warn(
              e,
              "Failed to serialize property %s:%s",
              propertyHolder.category(),
              propertyHolder.name());
        }

        categoryNode.add(property.getKey(), propertyNode);
      }

      result.add(category.getKey(), categoryNode);
    }

    return result;
  }