提问人:yann89 提问时间:9/12/2016 最后编辑:expertyann89 更新时间:2/20/2023 访问量:2419
如何将jgrapht简单图序列化为json?
How can I serialize a jgrapht simple graph to json?
问:
我有一个简单的有向图来自 jgrapht,我正在尝试使用 jackson 将其序列化为 JSON 文件,如下所示:
ObjectMapper mapper = new ObjectMapper();
File output = new File("P:\\tree.json");
ObjectWriter objectWriter = mapper.writer().withDefaultPrettyPrinter();
objectWriter.writeValue(output,simpleDirectedGraph);
但是,我收到此错误:
线程“main”com.fasterxml.jackson.databind.JsonMappingException中的异常:未找到类org.jgrapht.graph.AbstractBaseGraph$ArrayListFactory的序列化程序,并且未发现用于创建BeanSerializer的属性(为避免异常,请禁用SerializationFeature.FAIL_ON_EMPTY_BEANS) ) (通过引用链:org.jgrapht.graph.SimpleDirectedGraph[“edgeSetFactory”]) 在 com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.failForEmpty(UnknownSerializer.java:69) 在 com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.serialize(UnknownSerializer.java:32) 在 com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:693) 在 com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:675) 在 com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:157) 在 com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:130) 在 com.fasterxml.jackson.databind.ObjectWriter$Prefetch.serialize(ObjectWriter.java:1387) 在 com.fasterxml.jackson.databind.ObjectWriter._configAndWriteValue(ObjectWriter.java:1088) 在 com.fasterxml.jackson.databind.ObjectWriter.writeValue(ObjectWriter.java:909) 在 ms.fragment.JSONTreeGenerator.main(JSONTreeGenerator.java:45) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(本机方法) 在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在 java.lang.reflect.Method.invoke(Method.java:497) 在 com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
我已经看到有一个 GmlExporter,但我对 json 感兴趣......我该怎么做?
答:
您可以通过以下方式禁用该异常:
mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
你从杰克逊那里得到的例外:
JsonMappingException:未找到类 org.jgrapht.graph.AbstractBaseGraph$ArrayListFactory 的序列化程序 并且未发现用于创建 BeanSerializer 的属性 (为避免异常,请禁用 SerializationFeature.FAIL_ON_EMPTY_BEANS))(通过参考链: org.jgrapht.graph.SimpleDirectedGraph[“edgeSetFactory”]) 在 com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.failForEmpty(UnknownSerializer.java:69)
提供了有关如何解决的线索:
- 未发现用于创建 BeanSerializer 的属性
- 属性似乎是空的
SimpleDirectedGraph["edgeSetFactory"]
从序列化中排除属性类型:edgeSetFactory
AbstractBaseGraph$ArrayListFactory
编写自定义序列化程序
通常,Jackson 会使用 a 将任何非原始类写入 JSON。
不幸的是,这不适用于抽象类。StdBeanSerializer
因此,您可以编写自己的字段来处理特殊字段。JsonSerializer
您可以将 Graph 序列化为 XML,然后从 XML 序列化为 JSON :
序列化到 XML :您可以使用此库:XStream http://x-stream.github.io 它是一个小型库,可以轻松地在XML中序列化和反序列化。
图书馆使用指南 : http://x-stream.github.io/tutorial.html
之后,尝试使用以下命令将XML映射到JSON:
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20180813</version>
</dependency>
XML.java 是您要查找的类:
import org.json.JSONObject;
import org.json.XML;
import org.json.JSONException;
public class Main {
public static int PRETTY_PRINT_INDENT_FACTOR = 4;
public static String TEST_XML_STRING =
"<?xml version=\"1.0\" ?><test attrib=\"moretest\">Turn this to JSON</test>";
public static void main(String[] args) {
try {
JSONObject xmlJSONObj = XML.toJSONObject(TEST_XML_STRING);
String jsonPrettyPrintString = xmlJSONObj.toString(PRETTY_PRINT_INDENT_FACTOR);
System.out.println(jsonPrettyPrintString);
} catch (JSONException je) {
System.out.println(je.toString());
}
}
}
选项 1
较新版本的 JGraphT 内置了对使用该模块从 JSON 导入/导出图形的支持。jgrapht-io
下面是将图形导出为 JSON 的示例:
import org.jgrapht.Graph;
import org.jgrapht.graph.DefaultDirectedGraph;
import org.jgrapht.graph.DefaultEdge;
import org.jgrapht.nio.json.JSONExporter;
import java.net.URI;
import java.net.URISyntaxException;
public class Main {
public static void main(String[] args) throws Exception {
final var jsonExporter = new JSONExporter<URI, DefaultEdge>();
jsonExporter.exportGraph(
newSampleGraph(),
System.out
);
System.out.println("");
}
// Copied from https://jgrapht.org/guide/HelloJGraphT
private static Graph<URI, DefaultEdge> newSampleGraph() throws URISyntaxException {
Graph<URI, DefaultEdge> g = new DefaultDirectedGraph<>(DefaultEdge.class);
URI google = new URI("http://www.google.com");
URI wikipedia = new URI("http://www.wikipedia.org");
URI jgrapht = new URI("http://www.jgrapht.org");
// add the vertices
g.addVertex(google);
g.addVertex(wikipedia);
g.addVertex(jgrapht);
// add edges to create linking structure
g.addEdge(jgrapht, wikipedia);
g.addEdge(google, jgrapht);
g.addEdge(google, wikipedia);
g.addEdge(wikipedia, google);
return g;
}
}
供参考的文件:pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.stackoverflow</groupId>
<artifactId>questions-39438962</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>18</maven.compiler.source>
<maven.compiler.target>18</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.jgrapht</groupId>
<artifactId>jgrapht-core</artifactId>
<version>1.5.1</version>
</dependency>
<dependency>
<groupId>org.jgrapht</groupId>
<artifactId>jgrapht-io</artifactId>
<version>1.5.1</version>
</dependency>
</dependencies>
</project>
选项 2
为 JGraphT 图实现自定义 Jackson 序列化程序,将其注册到 ,并在序列化程序中实现逻辑。ObjectMapper
下面是一个示例:
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import org.jgrapht.Graph;
import org.jgrapht.nio.IntegerIdProvider;
import java.io.IOException;
public class DefaultDirectedGraphSerializer<V, E, T extends Graph<V, E>> extends StdSerializer<T> {
public DefaultDirectedGraphSerializer(Class<T> t) {
super(t);
}
public DefaultDirectedGraphSerializer() {
this(null);
}
@Override
public void serialize(T value, JsonGenerator gen, SerializerProvider provider) throws IOException {
final var idProvider = new IntegerIdProvider<>();
gen.writeStartObject();
gen.writeFieldName("graph");
gen.writeStartObject();
gen.writeFieldName("nodes");
gen.writeStartObject();
for (V v : value.vertexSet()) {
final var id = idProvider.apply(v);
gen.writeFieldName(id);
gen.writeStartObject();
gen.writeStringField("label", v.toString());
gen.writeEndObject();
}
gen.writeEndObject();
gen.writeFieldName("edges");
gen.writeStartArray();
for (E e : value.edgeSet()) {
gen.writeStartObject();
final var source = value.getEdgeSource(e);
final var target = value.getEdgeTarget(e);
gen.writeStringField("source", idProvider.apply(source));
gen.writeStringField("target", idProvider.apply(target));
gen.writeEndObject();
}
gen.writeEndArray();
gen.writeEndObject();
gen.writeEndObject();
}
}
import org.jgrapht.Graph;
import org.jgrapht.graph.DefaultDirectedGraph;
import org.jgrapht.graph.DefaultEdge;
import java.net.URI;
import java.net.URISyntaxException;
public class Graphs {
public static Graph<URI, DefaultEdge> newSampleGraph() throws URISyntaxException {
final var g = new DefaultDirectedGraph<URI, DefaultEdge>(DefaultEdge.class);
URI google = new URI("http://www.google.com");
URI wikipedia = new URI("http://www.wikipedia.org");
URI jgrapht = new URI("http://www.jgrapht.org");
g.addVertex(google);
g.addVertex(wikipedia);
g.addVertex(jgrapht);
g.addEdge(jgrapht, wikipedia);
g.addEdge(google, jgrapht);
g.addEdge(google, wikipedia);
g.addEdge(wikipedia, google);
return g;
}
}
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import org.jgrapht.graph.DefaultDirectedGraph;
import java.net.URISyntaxException;
import static org.example.Graphs.newSampleGraph;
public class Main {
public static void main(String[] args) throws URISyntaxException, JsonProcessingException {
final var module = new SimpleModule();
module.addSerializer(DefaultDirectedGraph.class, new DefaultDirectedGraphSerializer<>());
final ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(module);
System.out.println(mapper.writeValueAsString(newSampleGraph()));
}
}
这将生成以下 JSON 文档(在漂亮的打印之后):
{
"graph": {
"nodes": {
"1": {
"label": "http://www.google.com"
},
"2": {
"label": "http://www.wikipedia.org"
},
"3": {
"label": "http://www.jgrapht.org"
}
},
"edges": [
{
"source": "3",
"target": "2"
},
{
"source": "1",
"target": "3"
},
{
"source": "1",
"target": "2"
},
{
"source": "2",
"target": "1"
}
]
}
}
import org.jgrapht.Graph;
import org.jgrapht.io.JSONExporter;
import org.jgrapht.io.SimpleGraphExporter;
import org.jgrapht.io.SimpleGraphImporter;
import org.jgrapht.io.JSONImporter;
import org.jgrapht.io.JSONExporter;
import org.jgrapht.io.ExportException;
import org.jgrapht.io.ImportException;
// Create a new, empty simple graph
Graph<String, DefaultEdge> graph = new SimpleGraph<>(DefaultEdge.class);
// Add some vertices and edges to the graph
graph.addVertex("A");
graph.addVertex("B");
graph.addVertex("C");
graph.addEdge("A", "B");
graph.addEdge("B", "C");
// Create a new JSONExporter instance
JSONExporter<String, DefaultEdge> exporter = new JSONExporter<>();
// Export the graph to JSON
String json = exporter.toJson(graph);
评论