当前位置: 代码迷 >> java >> 有没有办法在 GSON 中使用一个类作为另一个类的变量类型?
  详细解决方案

有没有办法在 GSON 中使用一个类作为另一个类的变量类型?

热度:46   发布时间:2023-08-02 11:10:35.0

我正在使用 Java 和 GSON。 我有一个像这样的 json 数组:

[{"ID":1001,
  "name":"Egnatia-3isSeptembriou/Anatolika",
  "latitude":40.626216,
  "longitude":22.959864,
  "Edge":[
      {"destination_id":1030,"weight":6},
      {"destination_id":1012,"weight":12}]
},
{
  "ID":1002,
  "name":"Egnatia-3isSeptembriou/Boreia",
  "latitude":40.626055,
  "longitude":22.959845,
  "Edge":[
      {"destination_id":1025,"weight":3},
      {"destination_id":1008,"weight":5}]
}]

我想使用 GSON 制作两个类,例如:

public class Node {
    int ID;
    String name;
    double latitude, longitude; 
    int previous = 0;
    boolean visited = false;
    double distance = Double.MAX_VALUE;
    Edge[] Edge;
 }

public class Edge {
    Node destinationNode;
    double weight;
}

有没有一种优雅的方法来做到这一点,而不是每次都复制 Edge 中的所有节点变量?

谢谢!

如果类之间的关系像聚合一样简单,您总是从子级链接到父级,则可以编写自定义反序列化器。 就像在这个问题中一样: 。 在您的情况下,您有聚合器列表,其中内边缘指向同一列表中的其他聚合器。 我建议稍微更改您的模型并将新的Node属性添加到Edge类。 另外,为了避免序列化,我使用了transient关键字。 您可以更改它并使用@Expose注释,但在这种情况下, transient要简单得多。 我添加了SerializedName注释以使类中的属性具有更好的名称:

class Node {

    @SerializedName("ID")
    private int id;

    private String name;
    private double latitude, longitude;
    private int previous = 0;
    private boolean visited = false;
    private double distance = Double.MAX_VALUE;

    @SerializedName("Edge")
    private List<Edge> edges;

    // getters, setters, toString
}

class Edge {

    @SerializedName("destination_id")
    private int destinationId;
    private transient Node destinationNode;
    private double weight;

    // getters, setters, toString
}

我更改了一点JSON以供参考:

[
  {
    "ID": 1001,
    "name": "Egnatia-3isSeptembriou/Anatolika",
    "latitude": 40.626216,
    "longitude": 22.959864,
    "Edge": [
      {
        "destination_id": 1030,
        "weight": 6
      },
      {
        "destination_id": 1002,
        "weight": 12
      }
    ]
  },
  {
    "ID": 1002,
    "name": "Egnatia-3isSeptembriou/Boreia",
    "latitude": 40.626055,
    "longitude": 22.959845,
    "Edge": [
      {
        "destination_id": 1025,
        "weight": 3
      },
      {
        "destination_id": 1001,
        "weight": 5
      }
    ]
  }
]

现在,我们可以从给定的payload反序列化类,然后设置引用。

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.annotations.SerializedName;
import com.google.gson.reflect.TypeToken;

import java.io.File;
import java.io.FileReader;
import java.lang.reflect.Type;
import java.util.List;

public class GsonApp {

    public static void main(String[] args) throws Exception {
        File jsonFile = new File("./resource/test.json").getAbsoluteFile();
        Gson gson = new GsonBuilder()
                .setPrettyPrinting()
                .create();

        Type nodesType = new TypeToken<List<Node>>() {}.getType();
        List<Node> nodes = gson.fromJson(new FileReader(jsonFile), nodesType);
        nodes.forEach(node -> {
            nodes.forEach(node1 -> {
                node1.getEdges().forEach(edge -> {
                    if (node.getId() == edge.getDestinationId()) {
                        edge.setDestinationNode(node);
                    }
                });
            });
        });

        nodes.forEach(System.out::println);
    }
}

上面的代码打印:

Node{id=1001, name='Egnatia-3isSeptembriou/Anatolika', latitude=40.626216, longitude=22.959864, previous=0, visited=false, distance=1.7976931348623157E308, edges=[Edge{destinationId=1030, destinationNodeIsSet=false, weight=6.0}, Edge{destinationId=1002, destinationNodeIsSet=true, weight=12.0}]}
Node{id=1002, name='Egnatia-3isSeptembriou/Boreia', latitude=40.626055, longitude=22.959845, previous=0, visited=false, distance=1.7976931348623157E308, edges=[Edge{destinationId=1025, destinationNodeIsSet=false, weight=3.0}, Edge{destinationId=1001, destinationNodeIsSet=true, weight=5.0}]}