@SuppressWarnings("unchecked")
  private static <T extends JsonNode> T expandDots(T parent) {
    Objects.requireNonNull(parent, "parent");

    if (parent.isValueNode()) {
      return parent.deepCopy();
    }

    // ArrayNode
    if (parent.isArray()) {
      ArrayNode arr = (ArrayNode) parent;
      ArrayNode copy = arr.arrayNode();
      arr.elements().forEachRemaining(e -> copy.add(expandDots(e)));
      return (T) copy;
    }

    // ObjectNode
    ObjectNode objectNode = (ObjectNode) parent;
    final ObjectNode copy = objectNode.objectNode();
    objectNode.fields().forEachRemaining(e -> {
      final String property = e.getKey();
      final JsonNode node = e.getValue();

      final String[] names = property.split("\\.");
      ObjectNode copy2 = copy;
      for (int i = 0; i < names.length - 1; i++) {
        copy2 = copy2.with(names[i]);
      }
      copy2.set(names[names.length - 1], expandDots(node));
    });

    return (T) copy;
  }
Expands attributes with dots ({@code .}) into sub-nodes.
Use for more friendly JSON format:

<pre>
  {'a.b.c': 1}
  expanded to
  {a: { b: {c: 1}}}}
</pre>
@param parent current node
@param <T> type of node (usually JsonNode).
@return copy of existing node with field {@code a.b.c} expanded.
criteria/elasticsearch/test/org/immutables/criteria/elasticsearch/JsonChecker.java