Seite 1 von 1

Hilfe bei JSON und Dictionary

Verfasst: Samstag 8. Februar 2020, 22:13
von opccorsa
Hallo Leute, ich melde mich mal wieder seit langer Zeit hier im Forum mit einem Problem.
Ich habe eine JSON Datei wo ich mehrere Dict und Lists habe. Das einlesen und schreiben ist kein Problem. Leider komme ich nicht an die einzelnen Werte der JSON Datei. Ich habe es versucht mit parsen, rekursive und aktuell mit Ebenen. Ich bekomme im Moment ein Dictionary. Dieses bekomme ich auch nicht getrennt. Ziel des Ganzen wäre es z.B. einen String (conveyer__ip) bzw (conveyer__shuttle1__net_port) zu haben und das dazugehörige Value (12345) bzw. (13000). Ich hoffe ihr könnte mir ein wenig auf die Sprünge helfen.
LG :)

Code: Alles auswählen

#!/usr/bin/env python3
# coding: utf-8

import json

with open('data.json', 'r') as f:
    data = json.load(f)

def flatten_json(y):
    out = {}
    def flatten(x, name=''):
        if type(x) is dict:
            for a in x:
                flatten(x[a], name + a + '_')
        elif type(x) is list:
            i = 0
            for a in x:
                flatten(a, name + '_')
                i += 1
        else:
            out[name[:-1]] = x
    flatten(y)
    return out

test = flatten_json(data)
print(test,sep=",")
print(test.get("conveyer1__shuttle1__net_port"))

Code: Alles auswählen

{'conveyer1__shuttle1__net_port': '13000', 'conveyer1__shuttle1__track1__right__node1_type': 'can', 'conveyer1__shuttle1__track1__right__node1_port': '0', 'conveyer1__shuttle1__track1__right__node1_id': '20', 'conveyer1__shuttle1__track1__right__node1_io1__dir': '1', 'conveyer1__shuttle1__track1__right__node1_io1__type': 'Stopper', 'conveyer1__shuttle1__track1__right__node1_io2__dir': '0', 'conveyer1__shuttle1__track1__right__node1_io2__type': 'Stopini', 'conveyer1__shuttle1__track1__right__node1_io3__dir': None, 'conveyer1__shuttle1__track1__right__node1_io3__type': None, 'conveyer1__shuttle1__track1__right__node1_io4__dir': None, 'conveyer1__shuttle1__track1__right__node1_io4__type': None}
13000

Code: Alles auswählen

{
	"conveyer1": [{
		"ip": "12345",
		"shuttle1": [{
			"net_port": "13000",
			"track1": [{
				"right": [{
					"node1": {
						"type": "can",
						"port": "0",
						"id": "20",
						"io1": [{
							"dir": "1",
							"type": "Stopper"
						}],
						"io2": [{
							"dir": "0",
							"type": "Stopini"
						}],
						"io3": [{
							"dir": null,
							"type": null
						}],
						"io4": [{
							"dir": null,
							"type": null
						}],
						"motor1": [{
							"dir": {},
							"mode": {},
							"speed": {},
							"acc": {}
						}]
					}
				}],
				"left": [{
					"node1": {
						"type": {},
						"port": {},
						"id": {},
						"io1": [{
							"dir": {},
							"type": {}
						}],
						"io2": [{
							"dir": {},
							"type": {}
						}],
						"io3": [{
							"dir": {},
							"type": {}
						}],
						"io4": [{
							"dir": {},
							"type": {}
						}],
						"motor2": [{
							"dir": {},
							"mode": {},
							"speed": {},
							"acc": {}
						}]
					}
				}]
			}]
		}]
	}]
}

Re: Hilfe bei JSON und Dictionary

Verfasst: Samstag 8. Februar 2020, 22:31
von __blackjack__
@opccorsa: Sag mal kann das sein das alle Arrays in diesem JSON-Objekt immer genau *ein* JSON-Objekt enthalten‽ Wie sinnlos ist das denn? Also kann man die Listen einfach ignorieren. Wäre auch sonst interessant was da sonst passieren sollte.

Statt ``type(x) is SomeType`` würde man besser ``isinstance(x, SomeType)`` schreiben. Dann funktioniert das zum Beispiel auch noch wenn man da statt `dict` `OrderedDict` bekommen würde.

Re: Hilfe bei JSON und Dictionary

Verfasst: Samstag 8. Februar 2020, 22:47
von __blackjack__

Code: Alles auswählen

#!/usr/bin/env python3
import json
from functools import singledispatch
from pprint import pprint


@singledispatch
def visit(node, path):
    raise ValueError(repr(node))


@visit.register(type(None))
@visit.register(str)
def visit_simple_type(node, path):
    yield "_".join(path), node


@visit.register(dict)
def visit_object(node, path):
    for name, value in node.items():
        yield from visit(value, path + [name])


@visit.register(list)
def visit_array(node, path):
    if len(node) != 1:
        raise ValueError(f"unexpected length {len(node)} ({node!r})")
    yield from visit(node[0], path)


def flatten(data):
    return dict(visit(data, []))


def main():
    with open("test.json", "rb") as file:
        data = json.load(file)
    pprint(flatten(data))


if __name__ == "__main__":
    main()
Ausgabe für die Beispieldatei:

Code: Alles auswählen

{'conveyer1_ip': '12345',
 'conveyer1_shuttle1_net_port': '13000',
 'conveyer1_shuttle1_track1_right_node1_id': '20',
 'conveyer1_shuttle1_track1_right_node1_io1_dir': '1',
 'conveyer1_shuttle1_track1_right_node1_io1_type': 'Stopper',
 'conveyer1_shuttle1_track1_right_node1_io2_dir': '0',
 'conveyer1_shuttle1_track1_right_node1_io2_type': 'Stopini',
 'conveyer1_shuttle1_track1_right_node1_io3_dir': None,
 'conveyer1_shuttle1_track1_right_node1_io3_type': None,
 'conveyer1_shuttle1_track1_right_node1_io4_dir': None,
 'conveyer1_shuttle1_track1_right_node1_io4_type': None,
 'conveyer1_shuttle1_track1_right_node1_port': '0',
 'conveyer1_shuttle1_track1_right_node1_type': 'can'}