问题描述
我正在使用 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 中的所有节点变量?
谢谢!
1楼
    如果类之间的关系像聚合一样简单,您总是从子级链接到父级,则可以编写自定义反序列化器。 
    就像在这个问题中一样: 。 
    在您的情况下,您有聚合器列表,其中内边缘指向同一列表中的其他聚合器。 
    我建议稍微更改您的模型并将新的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}]}