PHP: Wie lese ich diese "Text"-Datenbank aus? (JSON-Ähnlich)

WulfmanGER

Commander
Registriert
Juli 2005
Beiträge
2.225
Hallo in die Runde,

ich nutze EMDB als Quelle für eine mySQL/PHP-Filmdatenbank. Ansich kann EMDB schon was gutes Exportieren - reicht nur leider nicht. Ich muss Personendaten aus der Datenbank rausziehen. Hier hab ich ein kleine Startproblem.

EMDB nutzt eine Text-Datenbank die man gut per Editor lesen kann (und ich mit php auslesen möchte)

Hier mal ein Beispiel:
das [RS] zeigt der Editor hier nicht an und ist von mir händisch im BEISPIEL eingetragen! RS ist ein "Record Seperator" - also eine "Feldtrennung"

Sieht auf den ersten Blick wie JSON aus - aber JSON fängt doch mit [ und geht mit {} weiter. Ist hier umgekehrt. Mit php und json_decode bekomme ich die nicht ausgelesen.

Code:
{
    "version": "70",
    "custom-genres": {},
    "custom-languages": {},
    "custom-services": {},
    "custom-versions": {},
    "collections": [],
    "tags": [],
    "movies": [{
        "title": "1984[RS]#ONineteen Eighty-Four[RS]Senator Film[RS]-1",
        "year": "1984[RS]0[RS]113[RS]#GB[RS]-10002[RS]0[RS]704x368[RS][RS]-2[RS]0[RS]1[RS]1[RS]0[RS]0[RS]2[RS]0,1[RS]0",
        "genres": "DS[RS]0087803|0[RS]20220228[RS]16[RS]1@0@0[RS][RS]0[RS]www.imdb.com/video/vi2065472025?playlistId=tt0087803&ref[RS][RS][RS]",
        "audio": "[RS][RS]1[RS]O0000G00B00",
        "cast": "0,1,2,3,4,5,6,7,8,9,10,11,12,13,14[RS]Winston Smith|O'Brien|Julia|Charrington|Parsons|Tillotson|Waiter|Mrs. Parsons|The Whore|Artsem Lecturer|Shouting Prole|Guard|Guard|Patrolman|Executioner|||||||||||||||||||",
        "plot": "In einer totalitären Gesellschaft der Zukunft versucht ein Mann, dessen Aufgabe es ist, die Geschichte umzuschreiben, mithilfe der Liebe zu rebellieren.",
        "tagline": "2+2=5[RS]",
        "rating": "47[RS]00[RS]00[RS]00[RS]00[RS][RS][RS]70934[RS]0[RS]999067[RS]",
        "custom-fields": "4425[RS]1984"
    }, {
        "title": "Zwei Himmelhunde auf dem Weg zur Hölle-1",

Wie lese ich sowas also aus? Kann man bei json_decode irgendwie die {[ vertauschen? ;) (per Texteditor alle [ = { ersetzen geht nicht, da ich im Titel oder im Plot durchaus [] haben kann)

---------------

Das nächste Problem ist die frage wie ich mit dem [RS] umgehe. Ich muss explizit "year" und "cast" auslesen. Year ist noch relativ einfach - da der Aufbau, Länge immer gleich ist - mit explode sollte das gehen? Dann nur die richtigen Positionen auslesen und zu ende Verarbeiten.

Bei CAST hab ich aber ein Problem
0,1,2,3 sind die Schauspieler-IDs nach dem RS kommen dann deren ROLLEN (die Übersetzung SchauspielID = Schauspieler kommt am Ende der Datenbank - nicht schön gemacht .... aber machbar - nette Herausforderung). Hier muss natürlich Position 1 mit Position 1 der Schauspieler-IDs zusammengefügt werden. Mein Quick&Dirty-Ansatz: Ich arbeite mit MEHREREN Arrays
1) explode mit [RS] als Trennzeichen. Jetzt hab ich ein Array mit IDs (noch am Stück) und Rollen (am Stück)
2) im Array nehme ich den ersten Wert (also 0,1,2,3,4...) und splitte den auf - in ein neues Array
3) das gleiche mit dem zweiten Wert (also Rolle|Rolle|Rolle)
=> Jetzt hätte ich 2 Arrays die ich jetzt mixen müsste und zwar so das Pos1 und Pos1 zusammenkommen usw.
Klingt KOMPLIZIERT ... vorallem wenn ich das ca. 4500x machen muss ...
Geht das saubere? Performanter?

Die ganze Datenbank ist echt nicht schön gemacht und Performancemässig für die Tonne - aber leider die einzige wo ich saubere IMPORTIEREN, Verarbeiten und EXPORTIEREN kann ... Sehe das jetzt als Herausforderung ;)

Danke schon mal für eure Ideen ;)
 
Was exakt ist es was wir da sehen - EMDB scheint ja EricsMovieDatabase zu sein.
Kommt das aus der EMDB api? kommt das sirekt aus einer Datenbank? Erstmal schaut das ja wie dictionaries aus, die es in php AFAIK nicht gibt.
oder ist es gar eine meoglichkeit ein mehrdimensionales array in PHP anzulegen (ich kann kein PHP, bzw lerne es immer nur wenn ich es gerade brauche. ,nur hier und da mal einen patch geschrieben)
Wulfman_SG schrieb:
Das nächste Problem ist die frage wie ich mit dem [RS] umgehe.
was soll das rs sein

Wulfman_SG schrieb:
Klingt KOMPLIZIERT ... vorallem wenn ich das ca. 4500x machen muss ...
sed, suchen und ersetzen in der IDE, mit einer For schleife drueber iterieren..

Wulfman_SG schrieb:
Geht das saubere? Performanter?
Ich wuerde alle daten in einer echten Datenbank halten Posgres bspw.
 
EricsMovieDatabase ... das Teil hat leider keine API. Das ist ja ein Windows-Tool. Die Datenbank liegt in einer emdb.dat. Man kann einen CSV-Export machen - der mir aber vom Umfang leider nicht reicht. Daher muss ich die emdb.dat auslesen und hier scheitere ich am Format was JSON sehr ähnlich ist ... aber "ähnlich" reicht leider nicht ;)

Hab gerade mal einen Auszug der DB in einen JSON-Validator gepackt - der sagt: ungültig.

1646091926666.png
 
JSON:
{
    "version": "70",
    "custom-genres": {},
    "custom-languages": {},
    "custom-services": {},
    "custom-versions": {},
    "collections": [],
    "tags": [],
    "movies": [{
        "title": "1984[RS]#ONineteen Eighty-Four[RS]Senator Film[RS]-1",
        "year": "1984[RS]0[RS]113[RS]#GB[RS]-10002[RS]0[RS]704x368[RS][RS]-2[RS]0[RS]1[RS]1[RS]0[RS]0[RS]2[RS]0,1[RS]0",
        "genres": "DS[RS]0087803|0[RS]20220228[RS]16[RS]1@0@0[RS][RS]0[RS]www.imdb.com/video/vi2065472025?playlistId=tt0087803&ref[RS][RS][RS]",
        "audio": "[RS][RS]1[RS]O0000G00B00",
        "cast": "0,1,2,3,4,5,6,7,8,9,10,11,12,13,14[RS]Winston Smith|O'Brien|Julia|Charrington|Parsons|Tillotson|Waiter|Mrs. Parsons|The Whore|Artsem Lecturer|Shouting Prole|Guard|Guard|Patrolman|Executioner|||||||||||||||||||",
        "plot": "In einer totalitären Gesellschaft der Zukunft versucht ein Mann, dessen Aufgabe es ist, die Geschichte umzuschreiben, mithilfe der Liebe zu rebellieren.",
        "tagline": "2+2=5[RS]",
        "rating": "47[RS]00[RS]00[RS]00[RS]00[RS][RS][RS]70934[RS]0[RS]999067[RS]",
        "custom-fields": "4425[RS]1984"
    }]
}

Ich finde ja, dass ist beinahe valides yaml.
json ist ein subset von yaml.
ich habe mal movies mit einer ] geschlossen, das komma entfernt und den rest mit } geschlossen und voila => valide. Frei nach dem Motto: Viele Wege fuehren nach YAML
https://jsonformatter.org/yaml-validator

Der hilft recht gut beim debuggen und macht dir das yaml etwas huebscher:
http://www.yamllint.com/
 
hab es auch gerade hinbekommen - das [RS] bzw. auch TABs werden nur nicht von json_decode akzeptiert (das ist hier ja nur als Platzhalter als [RS] geschrieben).

Aber explode unterstützt auch [RS] (ausgeschrieben) als Trennzeichen. Also erst alle [RS] (der Seperator) durch [RS] (also "vier Zeichen") ersetzen. Das wäre machbar! Damit hätte ich jetzt also ein json_decode-Kompatibles file. Wenn aber trotzdem wer eine Idee hat wie ich das Original-Trennzeichen trotzdem ausgelesen bekomme ... würde mir einen Schritt sparen ;)

Bliebe noch die Frage wie ich das "CAST"-Problem was ich oben beschrieben habe, saubere löse. Array-Orgie hört sich verdammt nach Quick&Dirty an ;)

Ich hab
Code:
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14[RS]Winston Smith|O'Brien|Julia|Charrington|Parsons|Tillotson|Waiter|Mrs. Parsons|The Whore|Artsem Lecturer|Shouting Prole|Guard|Guard|Patrolman|Executioner|||||||||||||||||||
Und ich muss anschließend haben
0 - Winston Smith
1 - O'Brien
2 - Julia

Das [RS] trennt die beiden Seiten. Wie löse ich das sauber?

Danke
 
Zuletzt bearbeitet:
Wulfman_SG schrieb:
JSON fängt doch mit [ und geht mit {} weiter.

Nein tut es nicht? :confused_alt:

Zumindest auf den ersten Blick sieht es wie ein simples JSON Objekt aus mit unstrukturiertem Inhalt... und zumindest das, was man da sieht im Codeblock, ist offensichtlich unvollständig. Nicht daß das ein besonderes Wunder wäre.

JSON:
= Objekt, Delimiter {}
= Array, Delimiter []

Mit der Notation [{ ... }] erhält man also ganz einfach ein Array mit einem Element.

Was allerdings tatsächlich stimmt, ist, das der eine oder andere JSON Generator "veraltet" ist und nicht (mehr) stringenten Anforderungen genügt. Angehängte Kommata ohne nachfolgendes Element waren mal zulässig, funktionieren auch teilweise noch, sind aber inzwischen kein valides JSON mehr.
Dasselbe wie die teilweise verbreitete Syntax ohne die Quotation Marks für den KEY, also key: "value" anstelle von "key": "value".

Der für JSON unstrukturierte Text in den Values muß natürlich unabhängig von JSON zusätzlich aufgelöst werden.
Im Sinne von JSON ist das natürlich Käse, aber ich vermute mal, die Idee war, die Datenbank möglichst klein zu halten.
(Oder man hat JSON später angeflanscht und hat die alten Strukturen nicht transformieren wollen. Keine Ahnung.)
 
  • Gefällt mir
Reaktionen: wahli
Wulfman_SG schrieb:
Sieht auf den ersten Blick wie JSON aus - aber JSON fängt doch mit [ und geht mit {} weiter.

Zunächst mal:
  • Das ist json, definitiv... "hallo" oder null ist auch gültiges Json... salopp gesagt ist praktisch alles, wo du in der Browser-Konsole sagen kannst: let x = <dein json> und der Browser keinen Fehler ausspuckt, gültiges JSON - wie der Name schon sagt: JavaScript Object Notation
  • Das es mit json_decode nicht geladen werden kann, liegt vermutlich daran, dass es nachträglich noch mal gesondert kodiert wurde (vermutlich, um das Auslesen etwas zu erschweren oder weil die Programmiersprache dadurch etwas vereinfacht)
    • Die Stellen, wo der Parser-Fehler auftritt, deuten darauf hin, dass es hauptsächlich mit Whitespaces oder Sonderzeichen innerhalb des JSON zu tun hat - vielleicht hat die Datei ein BOM (Byte Order Mark)

Wulfman_SG schrieb:
Das [RS] trennt die beiden Seiten. Wie löse ich das sauber?
Hier haste deine Lösung... aber mit Programmieren hat das was du machst, wenig zu tun - du hast ja nicht mal nen Ansatz gepostet. Lern lieber, wie es geht, haste mehr von.

PHP:
$str = "0,1,2,3,4,5,6,7,8,9,10,11,12,13,14[RS]Winston Smith|O'Brien|Julia|Charrington|Parsons|Tillotson|Waiter|Mrs. Parsons|The Whore|Artsem Lecturer|Shouting Prole|Guard|Guard|Patrolman|Executioner|||||||||||||||||||";

[$idString, $nameString] = explode("[RS]", $str);
$ids = explode(",", $idString);
$names = explode("|", $nameString);
$minCount = min(count($ids), count($names));
$cast = array_combine(array_slice($ids, 0, $minCount), array_slice($names, 0, $minCount));

foreach($cast as $id => $name) {
    echo $id." = ".$name."<br/>".PHP_EOL;
}
 
Wie @RalphS schon geschrieben hat, ist das JSON und die [] sind Arrays und {} enthalten ein Objekt. Die Werte selbst sind mit "" gekennzeichnet.
Was ein Wert selbst beinhaltet. ist ein anderes Thema und wenn hier ein unstrukturiertes Objekt mit selbst definierten Trennzeichen drin ist, muss du das zu Fuß lösen. Somit musst du selbst die Werte in geeignete Objektstrukturen mappen. Im Prinzip ist es relativ einfach, aber lästig.

Wenn es insgesamt wegen der selbst definierten Trennzeichen kein valides JSON ist, dann ersetze sie gegen dein selbst definiertes Trennzeichen.
 
Zuletzt bearbeitet:
Das Thema JSON oder nicht ist ja schon erledigt gewesen ;). Bin da wohl etwas verrutscht. Das JSON wurde mir vorallem deswegen als Invalid angezeigt weil ich Record Seperator/Tabstops genutzt hatte (das ist nämlich in JSON nicht eralubt - muss daher umgeschrieben werden in z.b. \t oder z.b. den Platzhalter [RS] - ersteres ist natürlich schöner). Kaum Entfernt ging das Teil sowohl durch den JSON-Test als auch durch json_decode durch.

sandreas schrieb:
Hier haste deine Lösung... aber mit Programmieren hat das was du machst, wenig zu tun - du hast ja nicht mal nen Ansatz gepostet. Lern lieber, wie es geht, haste mehr von.

Den Ansatz hatte ich oben als Quick&Dirty eigentlich beschrieben ... Array-Orgie - das sähe dann so aus:

Code:
$stringg = "0,1,2,3,4,5,6,7,8,9,10,11,12,13,14\tWinston Smith|O'Brien|Julia|Charrington|Parsons|Tillotson|Waiter|Mrs. Parsons|The Whore|Artsem Lecturer|Shouting Prole|Guard|Guard|Patrolman|Executioner123|||||||||||||||||||";
$string_array = explode("\t", $stringg);
$array_links = explode(",", $string_array[0]); # Array mit den IDs
$array_rechts = explode("|", $string_array[1]); # Array mit den Rollen

$out = array();
foreach ($array_links as $key => $value){
    $out[] = array_merge((array)$array_rechts[$key], (array)$value); # Arrays zu einem zusammenfügen
}

Und schon hab ich ein Array wo die "Linken" und "Rechten" Werte zusammen stehen. Wie oben beschrieben - mein Ansatz - der am Anfang ja nicht wirklich anders ist als deiner. Andere Schreibweise (kannte ich so bisher nicht). Das zusammenfügen mit array_combine gefällt mir bei dir definitiv besser als mein array_mergen. Danke ;)
 
Wulfman_SG schrieb:
Wie oben beschrieben - mein Ansatz - der am Anfang ja nicht wirklich anders ist als deiner.
Muss ich übersehen haben, sorry, mein Fehler. Wenn man das ganze jetzt noch mal mit Logik betrachtet, braucht man die IDs ja überhaupt nicht, weil es einfach nur von 0 - X durchnummeriert ist (was PHP bei Arrays ja standardmäßig tut). Es reicht also vermutlich schon sowas:

PHP:
$str = "0,1,2,3,4,5,6,7,8,9,10,11,12,13,14[RS]Winston Smith|O'Brien|Julia|Charrington|Parsons|Tillotson|Waiter|Mrs. Parsons|The Whore|Artsem Lecturer|Shouting Prole|Guard|Guard|Patrolman|Executioner|||||||||||||||||||";

[$idString, $nameString] = explode("[RS]", $str);
$cast = array_filter(explode("|", $nameString));

foreach($cast as $id => $name) {
    echo $id." = ".$name."<br/>".PHP_EOL;
}
 
du meinst
Code:
$str = "0,1,2,3,4,5,6,7,8,9,10,11,12,13,14
Nein - das ist der ersten Datensatz und nur durchnummeriert weil das die ersten 15 Schauspieler in der Datenbank sind.

Der zweite Datensatz sieht dann so aus: 15,16,17,0,1,18 usw. Also ich darf weder auf "Default"-Nummerierungen achten noch darf ich auf keinen Fall irgendwo was sortieren (die Namen zu 0,1,2,3,4,5) stehen in exakt dieser Reihenfolge (ohne Nummer!) am Ende des Files (also die Nummer 0 steht an der ersten Position, die 15 an der 16. Position - schön...)

Find dieses Datenbankkonstrukt ist recht schwer nachzuvollziehen ....... im YEAR und GENRE (auszug oben), sind z.b. auch Personen versteckt (Regie, Musik, Autor) - und versteckt mein ich genauso ... heißt: wenn das Tool mal ein Update bekommt => erstmal prüfen ob die Datenbankfelder noch an der gleichen Stelle stehen ... und vieles mehr ....
 
Zurück
Oben