如何将jgrapht简单图序列化为json?

How can I serialize a jgrapht simple graph to json?

提问人:yann89 提问时间:9/12/2016 最后编辑:expertyann89 更新时间:2/20/2023 访问量:2419

问:

我有一个简单的有向图来自 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 感兴趣......我该怎么做?

JSON 序列化 Jackson JGorpt

评论

0赞 jeff porter 7/31/2018
虽然这不能解决您的问题,但我怀疑您尝试连续化的对象包含对 AbstractBaseGraph$ArrayListFactory 的引用。这个工厂不是 POJO,你使用的框架无法解决如何将其转换为 JSON。如果可能的话,要么将其清空,要么将其从 JSON 转换中排除,要么告诉 JSON-Jacson 框架将其排除。
0赞 Ondra Žižka 6/10/2019
我认为你需要自己写。Jgrapht 的根对象不能保证是 POJO 的集合,即使它是,你也需要用 id 指向整个 JSON 树来打破循环。

答:

0赞 Mohamed Badouch 10/30/2019 #1

您可以通过以下方式禁用该异常:

mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
0赞 hc_dev 4/11/2021 #2

你从杰克逊那里得到的例外:

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

0赞 Oussama ZAGHDOUD 9/29/2021 #3

您可以将 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());
           }
       }
   }
0赞 Behrang Saeedzadeh 9/8/2022 #4

选项 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"
            }
        ]
    }
}
0赞 Rasmus Othar Kirketerp 12/8/2022 #5
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);