2017-02-11 2 views
0

Ich habe eine verschachtelte JSON-Datei, bestehend aus Schlüssel und Werte, die Zeichenfolge sind. Aber die Struktur der JSON-Datei ist nicht festgelegt, daher könnte sie manchmal in drei Ebenen verschachtelt sein, manchmal nur in zwei Ebenen. Ich frage mich, wie ich das im strikten Modus serialisieren könnte?Deserialize JSON in Hack Strict-Modus

"live" : { 
"host" : "localhost", 
"somevalue" : "nothing", 
"anobject" : { 
    "one" : "two", 
    "three" : "four", 
    "five" : { 
    "six" : "seven" 
    } 
} 

}

Wenn ich die Struktur des JSON wissen würde, würde ich einfach meine eigene Klasse für sie schreiben, aber da die Schlüssel nicht festgelegt sind, und auch die Verschachtelung in mehrere Ebenen sein könnte, Ich frage mich wirklich, wie ich ein solches Objekt in einen bestimmten Typ geschnitten habe.

Jede Hilfe oder Hinweise geschätzt

Antwort

0

Ich denke, invariant s Sie auch hier dienen. Zunächst einmal, kann es hilfreich sein zu wissen, dass Sie einen Schlüsselbaum streng in Hack geben kann:

<?hh // strict 
class KeyedTree<+Tk as arraykey, +T> { 
    public function __construct(
    private Map<Tk, KeyedTree<Tk, T>> $descendants = Map{}, 
    private ?T $v = null 
) {} 
} 

(Es muss eine Klasse sein, weil cyclic shape definitions are sadly not allowed)

ich es nicht versucht haben, noch, aber type_structure s und Fred Emmott's TypeAssert aussehen, um auch von Interesse sein. Wenn bekannt ist, dass ein Teil Ihres JSON-Blobs behoben ist, können Sie den verschachtelten, unsicheren Teil isolieren und mit invariant s einen Baum daraus erstellen. Im Grenzfall, wo die ganze Blob unbekannt ist, dann könnte man die TypeAssert auszuschneiden, da gibt es keine interessante feste Struktur zu behaupten:

use FredEmmott\TypeAssert\TypeAssert; 
class JSONParser { 
    const type Blob = shape(
     'live' => shape(
      'host' => string, // fixed 
      'somevalue' => string, // fixed 
      'anobject' => KeyedTree<arraykey, mixed> // nested and uncertain 
     ) 
    ); 
    public static function parse_json(string $json_str): this::Blob { 
     $json = json_decode($json_str, true); 
     invariant(!array_key_exists('anobject', $json), 'JSON is not properly formatted.'); 
     $json['anobject'] = self::DFS($json['anobject']); 
      // replace the uncertain array with a `KeyedTree` 
     return TypeAssert::matchesTypeStructure(
      type_structure(self::class, 'Blob'), 
      $json 
     ); 
     return $json; 
    } 
    public static function DFS(array<arraykey, mixed> $tree): KeyedTree<arraykey, mixed> { 
     $descendants = Map{}; 
     foreach($tree as $k => $v) { 
      if(is_array($v)) 
       $descendants[$k] = self::DFS($v); 
      else 
       $descendants[$k] = new KeyedTree(Map{}, $v); // leaf node 
     } 
     return new KeyedTree($descendants); 
    } 
} 

Auf der Straße, werden Sie noch containsKey Invarianten auf dem KeyedTree ergänzen haben, aber das ist die Realität mit unstrukturierten Daten in Hack.

+0

Vielen, vielen Dank für Ihre Eingabe! – Bearzi