We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Deserialisation artifacts in adjacency_graph
### Current Behavior

Serialising and deserialising a Graph using the matched pair json_graph.adjacency_data and json_graph.adjacency_graph produces a graph which is not equal to the incoming graph using the graphs_equal method.
This is because adjacency.py:152 and adjacency.py:156 set the edge attributes to a dictionary containing the successor node of the edge, rather than to the dictionary from which it has been popped:

    for i, d in enumerate(data["adjacency"]):
        source = mapping[i]
        for tdata in d:
            target_data = tdata.copy()
            target = target_data.pop(id_)
            if not multigraph:
                graph.add_edge(source, target)
                graph[source][target].update(tdata)  # Should be target_data, which has v removed
            else:
                ky = target_data.pop(key, None)
                graph.add_edge(source, target, key=ky)
                graph[source][target][ky].update(tdata)  # Should be target_data, which has v removed

### Expected Behavior

A Graph when serialised and deserialised with paired methods should be equal to itself, if its nodes are defined in a way to enable the equality.

### Steps to Reproduce


    def test_deserialized_graph_equal(self):
        G = nx.MultiGraph()
        G.add_edge(1, 2, key="first")
        G.add_edge(1, 2, key="second", color="blue")
        H = adjacency_graph(adjacency_data(G))
        assert graphs_equal(G, H) #  == False

### Environment

Python version: 3.10
NetworkX version: 2.8.6

### Additional context

I have a patchset ready to go with a fix, opening this bug report to attach to.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `networkx/readwrite/json_graph/adjacency.py`
Content:
```
1 from itertools import chain
2 
3 import networkx as nx
4 
5 __all__ = ["adjacency_data", "adjacency_graph"]
6 
7 _attrs = dict(id="id", key="key")
8 
9 
10 def adjacency_data(G, attrs=_attrs):
11     """Returns data in adjacency format that is suitable for JSON serialization
12     and use in Javascript documents.
13 
14     Parameters
15     ----------
16     G : NetworkX graph
17 
18     attrs : dict
19         A dictionary that contains two keys 'id' and 'key'. The corresponding
20         values provide the attribute names for storing NetworkX-internal graph
21         data. The values should be unique. Default value:
22         :samp:`dict(id='id', key='key')`.
23 
24         If some user-defined graph data use these attribute names as data keys,
25         they may be silently dropped.
26 
27     Returns
28     -------
29     data : dict
30        A dictionary with adjacency formatted data.
31 
32     Raises
33     ------
34     NetworkXError
35         If values in attrs are not unique.
36 
37     Examples
38     --------
39     >>> from networkx.readwrite import json_graph
40     >>> G = nx.Graph([(1, 2)])
41     >>> data = json_graph.adjacency_data(G)
42 
43     To serialize with json
44 
45     >>> import json
46     >>> s = json.dumps(data)
47 
48     Notes
49     -----
50     Graph, node, and link attributes will be written when using this format
51     but attribute keys must be strings if you want to serialize the resulting
52     data with JSON.
53 
54     The default value of attrs will be changed in a future release of NetworkX.
55 
56     See Also
57     --------
58     adjacency_graph, node_link_data, tree_data
59     """
60     multigraph = G.is_multigraph()
61     id_ = attrs["id"]
62     # Allow 'key' to be omitted from attrs if the graph is not a multigraph.
63     key = None if not multigraph else attrs["key"]
64     if id_ == key:
65         raise nx.NetworkXError("Attribute names are not unique.")
66     data = {}
67     data["directed"] = G.is_directed()
68     data["multigraph"] = multigraph
69     data["graph"] = list(G.graph.items())
70     data["nodes"] = []
71     data["adjacency"] = []
72     for n, nbrdict in G.adjacency():
73         data["nodes"].append(dict(chain(G.nodes[n].items(), [(id_, n)])))
74         adj = []
75         if multigraph:
76             for nbr, keys in nbrdict.items():
77                 for k, d in keys.items():
78                     adj.append(dict(chain(d.items(), [(id_, nbr), (key, k)])))
79         else:
80             for nbr, d in nbrdict.items():
81                 adj.append(dict(chain(d.items(), [(id_, nbr)])))
82         data["adjacency"].append(adj)
83     return data
84 
85 
86 def adjacency_graph(data, directed=False, multigraph=True, attrs=_attrs):
87     """Returns graph from adjacency data format.
88 
89     Parameters
90     ----------
91     data : dict
92         Adjacency list formatted graph data
93 
94     directed : bool
95         If True, and direction not specified in data, return a directed graph.
96 
97     multigraph : bool
98         If True, and multigraph not specified in data, return a multigraph.
99 
100     attrs : dict
101         A dictionary that contains two keys 'id' and 'key'. The corresponding
102         values provide the attribute names for storing NetworkX-internal graph
103         data. The values should be unique. Default value:
104         :samp:`dict(id='id', key='key')`.
105 
106     Returns
107     -------
108     G : NetworkX graph
109        A NetworkX graph object
110 
111     Examples
112     --------
113     >>> from networkx.readwrite import json_graph
114     >>> G = nx.Graph([(1, 2)])
115     >>> data = json_graph.adjacency_data(G)
116     >>> H = json_graph.adjacency_graph(data)
117 
118     Notes
119     -----
120     The default value of attrs will be changed in a future release of NetworkX.
121 
122     See Also
123     --------
124     adjacency_graph, node_link_data, tree_data
125     """
126     multigraph = data.get("multigraph", multigraph)
127     directed = data.get("directed", directed)
128     if multigraph:
129         graph = nx.MultiGraph()
130     else:
131         graph = nx.Graph()
132     if directed:
133         graph = graph.to_directed()
134     id_ = attrs["id"]
135     # Allow 'key' to be omitted from attrs if the graph is not a multigraph.
136     key = None if not multigraph else attrs["key"]
137     graph.graph = dict(data.get("graph", []))
138     mapping = []
139     for d in data["nodes"]:
140         node_data = d.copy()
141         node = node_data.pop(id_)
142         mapping.append(node)
143         graph.add_node(node)
144         graph.nodes[node].update(node_data)
145     for i, d in enumerate(data["adjacency"]):
146         source = mapping[i]
147         for tdata in d:
148             target_data = tdata.copy()
149             target = target_data.pop(id_)
150             if not multigraph:
151                 graph.add_edge(source, target)
152                 graph[source][target].update(tdata)
153             else:
154                 ky = target_data.pop(key, None)
155                 graph.add_edge(source, target, key=ky)
156                 graph[source][target][ky].update(tdata)
157     return graph
158
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/networkx/readwrite/json_graph/adjacency.py b/networkx/readwrite/json_graph/adjacency.py
--- a/networkx/readwrite/json_graph/adjacency.py
+++ b/networkx/readwrite/json_graph/adjacency.py
@@ -149,9 +149,9 @@
             target = target_data.pop(id_)
             if not multigraph:
                 graph.add_edge(source, target)
-                graph[source][target].update(tdata)
+                graph[source][target].update(target_data)
             else:
                 ky = target_data.pop(key, None)
                 graph.add_edge(source, target, key=ky)
-                graph[source][target][ky].update(tdata)
+                graph[source][target][ky].update(target_data)
     return graph

{"golden_diff": "diff --git a/networkx/readwrite/json_graph/adjacency.py b/networkx/readwrite/json_graph/adjacency.py\n--- a/networkx/readwrite/json_graph/adjacency.py\n+++ b/networkx/readwrite/json_graph/adjacency.py\n@@ -149,9 +149,9 @@\n             target = target_data.pop(id_)\n             if not multigraph:\n                 graph.add_edge(source, target)\n-                graph[source][target].update(tdata)\n+                graph[source][target].update(target_data)\n             else:\n                 ky = target_data.pop(key, None)\n                 graph.add_edge(source, target, key=ky)\n-                graph[source][target][ky].update(tdata)\n+                graph[source][target][ky].update(target_data)\n     return graph\n", "issue": "Deserialisation artifacts in adjacency_graph\n### Current Behavior\r\n\r\nSerialising and deserialising a Graph using the matched pair json_graph.adjacency_data and json_graph.adjacency_graph produces a graph which is not equal to the incoming graph using the graphs_equal method.\r\nThis is because adjacency.py:152 and adjacency.py:156 set the edge attributes to a dictionary containing the successor node of the edge, rather than to the dictionary from which it has been popped:\r\n\r\n    for i, d in enumerate(data[\"adjacency\"]):\r\n        source = mapping[i]\r\n        for tdata in d:\r\n            target_data = tdata.copy()\r\n            target = target_data.pop(id_)\r\n            if not multigraph:\r\n                graph.add_edge(source, target)\r\n                graph[source][target].update(tdata)  # Should be target_data, which has v removed\r\n            else:\r\n                ky = target_data.pop(key, None)\r\n                graph.add_edge(source, target, key=ky)\r\n                graph[source][target][ky].update(tdata)  # Should be target_data, which has v removed\r\n\r\n### Expected Behavior\r\n\r\nA Graph when serialised and deserialised with paired methods should be equal to itself, if its nodes are defined in a way to enable the equality.\r\n\r\n### Steps to Reproduce\r\n\r\n\r\n    def test_deserialized_graph_equal(self):\r\n        G = nx.MultiGraph()\r\n        G.add_edge(1, 2, key=\"first\")\r\n        G.add_edge(1, 2, key=\"second\", color=\"blue\")\r\n        H = adjacency_graph(adjacency_data(G))\r\n        assert graphs_equal(G, H) #  == False\r\n\r\n### Environment\r\n\r\nPython version: 3.10\r\nNetworkX version: 2.8.6\r\n\r\n### Additional context\r\n\r\nI have a patchset ready to go with a fix, opening this bug report to attach to.\n", "before_files": [{"content": "from itertools import chain\n\nimport networkx as nx\n\n__all__ = [\"adjacency_data\", \"adjacency_graph\"]\n\n_attrs = dict(id=\"id\", key=\"key\")\n\n\ndef adjacency_data(G, attrs=_attrs):\n    \"\"\"Returns data in adjacency format that is suitable for JSON serialization\n    and use in Javascript documents.\n\n    Parameters\n    ----------\n    G : NetworkX graph\n\n    attrs : dict\n        A dictionary that contains two keys 'id' and 'key'. The corresponding\n        values provide the attribute names for storing NetworkX-internal graph\n        data. The values should be unique. Default value:\n        :samp:`dict(id='id', key='key')`.\n\n        If some user-defined graph data use these attribute names as data keys,\n        they may be silently dropped.\n\n    Returns\n    -------\n    data : dict\n       A dictionary with adjacency formatted data.\n\n    Raises\n    ------\n    NetworkXError\n        If values in attrs are not unique.\n\n    Examples\n    --------\n    >>> from networkx.readwrite import json_graph\n    >>> G = nx.Graph([(1, 2)])\n    >>> data = json_graph.adjacency_data(G)\n\n    To serialize with json\n\n    >>> import json\n    >>> s = json.dumps(data)\n\n    Notes\n    -----\n    Graph, node, and link attributes will be written when using this format\n    but attribute keys must be strings if you want to serialize the resulting\n    data with JSON.\n\n    The default value of attrs will be changed in a future release of NetworkX.\n\n    See Also\n    --------\n    adjacency_graph, node_link_data, tree_data\n    \"\"\"\n    multigraph = G.is_multigraph()\n    id_ = attrs[\"id\"]\n    # Allow 'key' to be omitted from attrs if the graph is not a multigraph.\n    key = None if not multigraph else attrs[\"key\"]\n    if id_ == key:\n        raise nx.NetworkXError(\"Attribute names are not unique.\")\n    data = {}\n    data[\"directed\"] = G.is_directed()\n    data[\"multigraph\"] = multigraph\n    data[\"graph\"] = list(G.graph.items())\n    data[\"nodes\"] = []\n    data[\"adjacency\"] = []\n    for n, nbrdict in G.adjacency():\n        data[\"nodes\"].append(dict(chain(G.nodes[n].items(), [(id_, n)])))\n        adj = []\n        if multigraph:\n            for nbr, keys in nbrdict.items():\n                for k, d in keys.items():\n                    adj.append(dict(chain(d.items(), [(id_, nbr), (key, k)])))\n        else:\n            for nbr, d in nbrdict.items():\n                adj.append(dict(chain(d.items(), [(id_, nbr)])))\n        data[\"adjacency\"].append(adj)\n    return data\n\n\ndef adjacency_graph(data, directed=False, multigraph=True, attrs=_attrs):\n    \"\"\"Returns graph from adjacency data format.\n\n    Parameters\n    ----------\n    data : dict\n        Adjacency list formatted graph data\n\n    directed : bool\n        If True, and direction not specified in data, return a directed graph.\n\n    multigraph : bool\n        If True, and multigraph not specified in data, return a multigraph.\n\n    attrs : dict\n        A dictionary that contains two keys 'id' and 'key'. The corresponding\n        values provide the attribute names for storing NetworkX-internal graph\n        data. The values should be unique. Default value:\n        :samp:`dict(id='id', key='key')`.\n\n    Returns\n    -------\n    G : NetworkX graph\n       A NetworkX graph object\n\n    Examples\n    --------\n    >>> from networkx.readwrite import json_graph\n    >>> G = nx.Graph([(1, 2)])\n    >>> data = json_graph.adjacency_data(G)\n    >>> H = json_graph.adjacency_graph(data)\n\n    Notes\n    -----\n    The default value of attrs will be changed in a future release of NetworkX.\n\n    See Also\n    --------\n    adjacency_graph, node_link_data, tree_data\n    \"\"\"\n    multigraph = data.get(\"multigraph\", multigraph)\n    directed = data.get(\"directed\", directed)\n    if multigraph:\n        graph = nx.MultiGraph()\n    else:\n        graph = nx.Graph()\n    if directed:\n        graph = graph.to_directed()\n    id_ = attrs[\"id\"]\n    # Allow 'key' to be omitted from attrs if the graph is not a multigraph.\n    key = None if not multigraph else attrs[\"key\"]\n    graph.graph = dict(data.get(\"graph\", []))\n    mapping = []\n    for d in data[\"nodes\"]:\n        node_data = d.copy()\n        node = node_data.pop(id_)\n        mapping.append(node)\n        graph.add_node(node)\n        graph.nodes[node].update(node_data)\n    for i, d in enumerate(data[\"adjacency\"]):\n        source = mapping[i]\n        for tdata in d:\n            target_data = tdata.copy()\n            target = target_data.pop(id_)\n            if not multigraph:\n                graph.add_edge(source, target)\n                graph[source][target].update(tdata)\n            else:\n                ky = target_data.pop(key, None)\n                graph.add_edge(source, target, key=ky)\n                graph[source][target][ky].update(tdata)\n    return graph\n", "path": "networkx/readwrite/json_graph/adjacency.py"}], "after_files": [{"content": "from itertools import chain\n\nimport networkx as nx\n\n__all__ = [\"adjacency_data\", \"adjacency_graph\"]\n\n_attrs = dict(id=\"id\", key=\"key\")\n\n\ndef adjacency_data(G, attrs=_attrs):\n    \"\"\"Returns data in adjacency format that is suitable for JSON serialization\n    and use in Javascript documents.\n\n    Parameters\n    ----------\n    G : NetworkX graph\n\n    attrs : dict\n        A dictionary that contains two keys 'id' and 'key'. The corresponding\n        values provide the attribute names for storing NetworkX-internal graph\n        data. The values should be unique. Default value:\n        :samp:`dict(id='id', key='key')`.\n\n        If some user-defined graph data use these attribute names as data keys,\n        they may be silently dropped.\n\n    Returns\n    -------\n    data : dict\n       A dictionary with adjacency formatted data.\n\n    Raises\n    ------\n    NetworkXError\n        If values in attrs are not unique.\n\n    Examples\n    --------\n    >>> from networkx.readwrite import json_graph\n    >>> G = nx.Graph([(1, 2)])\n    >>> data = json_graph.adjacency_data(G)\n\n    To serialize with json\n\n    >>> import json\n    >>> s = json.dumps(data)\n\n    Notes\n    -----\n    Graph, node, and link attributes will be written when using this format\n    but attribute keys must be strings if you want to serialize the resulting\n    data with JSON.\n\n    The default value of attrs will be changed in a future release of NetworkX.\n\n    See Also\n    --------\n    adjacency_graph, node_link_data, tree_data\n    \"\"\"\n    multigraph = G.is_multigraph()\n    id_ = attrs[\"id\"]\n    # Allow 'key' to be omitted from attrs if the graph is not a multigraph.\n    key = None if not multigraph else attrs[\"key\"]\n    if id_ == key:\n        raise nx.NetworkXError(\"Attribute names are not unique.\")\n    data = {}\n    data[\"directed\"] = G.is_directed()\n    data[\"multigraph\"] = multigraph\n    data[\"graph\"] = list(G.graph.items())\n    data[\"nodes\"] = []\n    data[\"adjacency\"] = []\n    for n, nbrdict in G.adjacency():\n        data[\"nodes\"].append(dict(chain(G.nodes[n].items(), [(id_, n)])))\n        adj = []\n        if multigraph:\n            for nbr, keys in nbrdict.items():\n                for k, d in keys.items():\n                    adj.append(dict(chain(d.items(), [(id_, nbr), (key, k)])))\n        else:\n            for nbr, d in nbrdict.items():\n                adj.append(dict(chain(d.items(), [(id_, nbr)])))\n        data[\"adjacency\"].append(adj)\n    return data\n\n\ndef adjacency_graph(data, directed=False, multigraph=True, attrs=_attrs):\n    \"\"\"Returns graph from adjacency data format.\n\n    Parameters\n    ----------\n    data : dict\n        Adjacency list formatted graph data\n\n    directed : bool\n        If True, and direction not specified in data, return a directed graph.\n\n    multigraph : bool\n        If True, and multigraph not specified in data, return a multigraph.\n\n    attrs : dict\n        A dictionary that contains two keys 'id' and 'key'. The corresponding\n        values provide the attribute names for storing NetworkX-internal graph\n        data. The values should be unique. Default value:\n        :samp:`dict(id='id', key='key')`.\n\n    Returns\n    -------\n    G : NetworkX graph\n       A NetworkX graph object\n\n    Examples\n    --------\n    >>> from networkx.readwrite import json_graph\n    >>> G = nx.Graph([(1, 2)])\n    >>> data = json_graph.adjacency_data(G)\n    >>> H = json_graph.adjacency_graph(data)\n\n    Notes\n    -----\n    The default value of attrs will be changed in a future release of NetworkX.\n\n    See Also\n    --------\n    adjacency_graph, node_link_data, tree_data\n    \"\"\"\n    multigraph = data.get(\"multigraph\", multigraph)\n    directed = data.get(\"directed\", directed)\n    if multigraph:\n        graph = nx.MultiGraph()\n    else:\n        graph = nx.Graph()\n    if directed:\n        graph = graph.to_directed()\n    id_ = attrs[\"id\"]\n    # Allow 'key' to be omitted from attrs if the graph is not a multigraph.\n    key = None if not multigraph else attrs[\"key\"]\n    graph.graph = dict(data.get(\"graph\", []))\n    mapping = []\n    for d in data[\"nodes\"]:\n        node_data = d.copy()\n        node = node_data.pop(id_)\n        mapping.append(node)\n        graph.add_node(node)\n        graph.nodes[node].update(node_data)\n    for i, d in enumerate(data[\"adjacency\"]):\n        source = mapping[i]\n        for tdata in d:\n            target_data = tdata.copy()\n            target = target_data.pop(id_)\n            if not multigraph:\n                graph.add_edge(source, target)\n                graph[source][target].update(target_data)\n            else:\n                ky = target_data.pop(key, None)\n                graph.add_edge(source, target, key=ky)\n                graph[source][target][ky].update(target_data)\n    return graph\n", "path": "networkx/readwrite/json_graph/adjacency.py"}]}