apoc.convert.Json Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of apoc-core Show documentation
Show all versions of apoc-core Show documentation
Core package for Neo4j Procedures
The newest version!
/*
* Copyright (c) "Neo4j"
* Neo4j Sweden AB [http://neo4j.com]
*
* This file is part of Neo4j.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package apoc.convert;
import static apoc.util.Util.labelStrings;
import static apoc.util.Util.map;
import apoc.meta.Types;
import apoc.result.MapResult;
import apoc.util.JsonUtil;
import apoc.util.Util;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import org.neo4j.graphdb.Entity;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Path;
import org.neo4j.graphdb.Relationship;
import org.neo4j.procedure.*;
public class Json {
// visible for testing
public static String NODE = "node";
public static String RELATIONSHIP = "relationship";
public static Object writeJsonResult(Object value) {
Types type = Types.of(value);
switch (type) {
case NODE:
return nodeToMap((Node) value);
case RELATIONSHIP:
return relToMap((Relationship) value);
case PATH:
return writeJsonResult(StreamSupport.stream(((Path) value).spliterator(), false)
.map(i -> i instanceof Node ? nodeToMap((Node) i) : relToMap((Relationship) i))
.collect(Collectors.toList()));
case LIST:
return ConvertUtils.convertToList(value).stream()
.map(Json::writeJsonResult)
.collect(Collectors.toList());
case MAP:
return ((Map) value)
.entrySet().stream()
.collect(
HashMap::new, // workaround for https://bugs.openjdk.java.net/browse/JDK-8148463
(mapAccumulator, entry) ->
mapAccumulator.put(entry.getKey(), writeJsonResult(entry.getValue())),
HashMap::putAll);
default:
return value;
}
}
private static Map relToMap(Relationship rel) {
Map mapRel = map(
"id", String.valueOf(rel.getId()),
"type", RELATIONSHIP,
"label", rel.getType().toString(),
"start", nodeToMap(rel.getStartNode()),
"end", nodeToMap(rel.getEndNode()));
return mapWithOptionalProps(mapRel, rel.getAllProperties());
}
private static Map nodeToMap(Node node) {
Map mapNode = map("id", String.valueOf(node.getId()));
mapNode.put("type", NODE);
if (node.getLabels().iterator().hasNext()) {
mapNode.put("labels", labelStrings(node));
}
return mapWithOptionalProps(mapNode, node.getAllProperties());
}
private static Map mapWithOptionalProps(Map mapEntity, Map props) {
if (!props.isEmpty()) {
mapEntity.put("properties", props);
}
return mapEntity;
}
@UserFunction("apoc.json.path")
@Description("Returns the given JSON path.")
public Object path(
@Name("json") String json,
@Name(value = "path", defaultValue = "$") String path,
@Name(value = "pathOptions", defaultValue = "null") List pathOptions) {
return JsonUtil.parse(json, path, Object.class, pathOptions);
}
@UserFunction("apoc.convert.toJson")
@Description("Serializes the given JSON value.")
public String toJson(@Name("value") Object value) {
try {
return JsonUtil.OBJECT_MAPPER.writeValueAsString(writeJsonResult(value));
} catch (IOException e) {
throw new RuntimeException("Can't convert " + value + " to json", e);
}
}
@Procedure(name = "apoc.convert.setJsonProperty", mode = Mode.WRITE)
@Description("Serializes the given JSON object and sets it as a property on the given `NODE`.")
public void setJsonProperty(@Name("node") Node node, @Name("key") String key, @Name("value") Object value) {
try {
node.setProperty(key, JsonUtil.OBJECT_MAPPER.writeValueAsString(value));
} catch (IOException e) {
throw new RuntimeException("Can't convert " + value + " to json", e);
}
}
@UserFunction("apoc.convert.getJsonProperty")
@Description(
"Converts a serialized JSON object from the property of the given `NODE` into the equivalent Cypher structure (e.g. `MAP`, `LIST`).")
public Object getJsonProperty(
@Name("node") Node node,
@Name("key") String key,
@Name(value = "path", defaultValue = "") String path,
@Name(value = "pathOptions", defaultValue = "null") List pathOptions) {
String value = (String) node.getProperty(key, null);
return JsonUtil.parse(value, path, Object.class, pathOptions);
}
@UserFunction("apoc.convert.getJsonPropertyMap")
@Description("Converts a serialized JSON object from the property of the given `NODE` into a Cypher `MAP`.")
public Map getJsonPropertyMap(
@Name("node") Node node,
@Name("key") String key,
@Name(value = "path", defaultValue = "") String path,
@Name(value = "pathOptions", defaultValue = "null") List pathOptions) {
String value = (String) node.getProperty(key, null);
return JsonUtil.parse(value, path, Map.class, pathOptions);
}
@UserFunction("apoc.convert.fromJsonMap")
@Description("Converts the given JSON map into a Cypher `MAP`.")
public Map fromJsonMap(
@Name("map") String value,
@Name(value = "path", defaultValue = "") String path,
@Name(value = "pathOptions", defaultValue = "null") List pathOptions) {
return JsonUtil.parse(value, path, Map.class, pathOptions);
}
@UserFunction("apoc.convert.fromJsonList")
@Description("Converts the given JSON list into a Cypher `LIST`.")
public List