JSON teil aus string extracten?
Hallo zusammen
Ich muss aus einem string den JSON teil einzeln extracten und das attribut, das hinten dran ist extracten. (In pyhton)
Anschliessend muss ich mit diesem attribut die korrekte liste im JSON string ausgeben.
Irgendwie schaffe ich es nicht.
also der string sieht etwa so aus:
'{"tarahumar": 2003, "fustier": ["grugrus", "swadeshi", "trillionize", "unpoeticized", "pseudoperipteral", "drakefly", "towaway"], "obtainers": "henchman", "stranglingly": "podded", "quatorzain": 2828.6, "funnel": "coscoroba", "motherly": 1070, "equitation": 4590, "nongraphitic": ["overhumane", "natica", "raspberries", "digestedly", "choraleon", "hypoleucocytosis"], "puckerier": "illegitimated"} equitation'
Mit dem letzten wort (equitation) muss ich dann die korrekte liste mit print() ausgeben.
Könntet ihr mir da echt auf die Sprünge helfen?
3 Antworten
Genau hierfür gibt es:
https://docs.python.org/3/library/json.html
Wenn Du den String erst zerlegen mußt:
>>> s='JSON string be here equitation and more shit here'
>>> s.partition('equitation')
('JSON string be here ', 'equitation', ' and more shit here')
Kann man das trivial auch so machen und auch noch strippen etc. .
Und das heißt in letzter Konsequenz, sei s Dein string:
import json
data=json.loads(s.partition('equitation')[0])
und fertig wäre das ganze (ohen Fehlerbehandlugn versteht sich).
...wär zu schön, aber innerhab des "legitimen" Teils steckt leider auch schon ein:
{..., "equitation": 4590,...} damit würde der string bereits dort getrennt und nicht am letzten vorkommen . ganz so simpel ist es auch nicht.
Meine Variante alles zwischen der ersten"{" und der letzten"}" abzufischen ist auch nicht Narrensicher und verlässt sich darauf, dass alle Klammern dazwischen im Gleichgewicht sind.
Eine perfekte Lösung für dergleichen gibt's wahrscheinlich nicht...
Beim angebenen Beispiel könnte man beim Seperator auch einfach ein Leerzeichen ergänzen.
Und klar könnte man auch nen re.split() o.ä. nehmen - aber um das zu beurteilen bräuchte man die Datenbasis.
Denn wenn alle Stricke reißen, müßte man einfach einen abgewandelten JSON-Decoder bauen, der den korrekten JSON-Teil aus dem String konsumiert und dann 10 grade sein lässt.
Aber da sind einfach zu viele wenn, aber und die Präzision der Problembeschreibung in der Frage lässt auch sehr zu wünschen übrig.
Da Dein Strig kein legitimes JSON ist, steigt der Parser natürlich mit einer Fehlermeldung bezüglich "Extradata" aus.
'{...} equitation' gehört hier nicht mehr zu json! und der Parser weiß nicht was er damit anfangen soll.
ich würde es (in diesem Fall) einfach mit der "Brechstange" also plumber Stringakrobatik lösen. Dafür bietet sich ei kleine RegEx an:
"\{.*\}"
- beginn des Suchstrings mit {
- belibige Zeichen .* (* ist gefräßig, also frist er bis zum letzten Matchcharacter im definierten Pattern)
- ende des Suchstrings mit }
Butter bei die Fische:
badJSON = '{"tarahumar": 2003, "fustier": ["grugrus", "swadeshi", "trillionize", "unpoeticized", "pseudoperipteral", "drakefly", "towaway"], "obtainers": "henchman", "stranglingly": "podded", "quatorzain": 2828.6, "funnel": "coscoroba", "motherly": 1070, "equitation": 4590, "nongraphitic": ["overhumane", "natica", "raspberries", "digestedly", "choraleon", "hypoleucocytosis"], "puckerier": "illegitimated"} equitation'
matches = re.findall("\{.*\}", badJSON) #extrahiere alles von der ersten bis zur letzten geschweiften Klammer
pureJSONString = ''.join(matches) #mache aus der Liste von Treffern (sollte nur einer sein) einen String
print(pureJSONString)
#Mal probieren obs der JSONparser schluckt . jetz sollte keine Fehlermeldung kommen
MyObject = json.loads(pureJSONString)
print(MyObject)
Die Lösung per brutaler Stringverarbeitung ist nicht schön. ...aber ainfach zu handhaben😤😏.
Ich mache mir Mühe, importiere kein json-Modul, kein json.loads() und was machst du?! Eiskalt die Lösung präsentieren! :-D
das jsonmodul habe ich auch nur zum testen verwendet.
ich bin eigentlich kein "Pythoner" (oder wie die sich nennen) .
Im Prinzip hilft bei irgendwelchen kaputten Zeug auch in anderen Sprachen der Weg über Stringverarbeitung.
in Powershell hätte ich noch weniger Zirkus veranstaltet:
$badJSON = '{"tarahumar": 2003, "fustier": ["grugrus", "swadeshi", "trillionize", "unpoeticized", "pseudoperipteral", "drakefly", "towaway"], "obtainers": "henchman", "stranglingly": "podded", "quatorzain": 2828.6, "funnel": "coscoroba", "motherly": 1070, "equitation": 4590, "nongraphitic": ["overhumane", "natica", "raspberries", "digestedly", "choraleon", "hypoleucocytosis"], "puckerier": "illegitimated"} equitation'
[Regex]::Matches($badJSON,'\{.*\}').Value|ConvertFrom-Json|fl *
Oder in C#:
var badJson = """
{"tarahumar": 2003, "fustier": ["grugrus", "swadeshi", "trillionize", "unpoeticized", "pseudoperipteral", "drakefly", "towaway"], "obtainers": "henchman", "stranglingly": "podded", "quatorzain": 2828.6, "funnel": "coscoroba", "motherly": 1070, "equitation": 4590, "nongraphitic": ["overhumane", "natica", "raspberries", "digestedly", "choraleon", "hypoleucocytosis"], "puckerier": "illegitimated"} equitatio
""";
var goodJson = badJson.Substring(badJson.IndexOf('{'), badJson.LastIndexOf('}') + 1);
var jsonObj = JsonSerializer.Deserialize<JsonObject>(goodJson);
Console.WriteLine(jsonObj);
Oder wenn es in einer Zeile sein soll:
Console.WriteLine(JsonSerializer.Deserialize<JsonObject>(badJson.Substring(badJson.IndexOf('{'), badJson.LastIndexOf('}') + 1)));
====================================
Ich kann nicht lesen, daher eine Korrektur :)
====================================
Mit RegEx kannst du nach equitation suchen und es durch "}" ersetzen.
Dies geschieht so:
import re
# Suche bitte nach equitation und zwar nur,
# wenn unmittelbar davor das Zeichen } steht.
regex = r"[}](equitation)"
# Es wird später entfernt und die leere Stelle muss
# selbstverständlich wieder befüllt werden
substitution = "}"
# Selbsterklärend
new_dict: dict = ""
# Deine Rohdaten
raw_data = """{
"tarahumar": 2003,
"fustier": [
"grugrus",
"swadeshi",
"trillionize",
"unpoeticized",
"pseudoperipteral",
"drakefly",
"towaway"
],
"obtainers": "henchman",
"stranglingly": "podded",
"quatorzain": 2828.6,
"funnel": "coscoroba",
"motherly": 1070,
"equitation": 4590,
"nongraphitic": [
"overhumane",
"natica",
"raspberries",
"digestedly",
"choraleon",
"hypoleucocytosis"
],
"puckerier": "illegitimated"
}equitation"""
result = re.sub(regex, substitution, raw_data, 0, re.MULTILINE)
Wurde equitation gefunden, wird das Ergebnis in "result" gespeichert.
Vorher bitte prüfen, ob result tatsächlich Daten hat und die Daten zur Verfügung stehen.
if result:
new_data = result
print(new_data)
"new_data" hat nun eine saubere JSON-Struktur (da Dictionary) und du kannst die Werte auslesen - ABER das überlasse ich dir :-)
Ausgabe:
{
"tarahumar": 2003,
"fustier": [
"grugrus",
"swadeshi",
"trillionize",
"unpoeticized",
"pseudoperipteral",
"drakefly",
"towaway"
],
"obtainers": "henchman",
"stranglingly": "podded",
"quatorzain": 2828.6,
"funnel": "coscoroba",
"motherly": 1070,
"equitation": 4590,
"nongraphitic": [
"overhumane",
"natica",
"raspberries",
"digestedly",
"choraleon",
"hypoleucocytosis"
],
"puckerier": "illegitimated"
}
Darauf bin ich auch reingefallen, seine Struktur endet allerdings bei
und es ist insgesamt ein String.