2017-02-11 62 views
0

我有一個嵌套的JSON文件,它由鍵和值組成,它們只是字符串。但是JSON文件的結構並不固定,所以有時它可以嵌套3層,有時只有2層。 我想知道我可以如何在嚴格模式下序列化?在嚴格模式下反序列化JSON

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

}

如果我想知道JSON的結構,我只是會寫我自己的類,但由於密鑰是不固定的,並且還嵌套可以分成幾個層次,我真的很想知道如何將這樣一個對象切割成特定的類型。

任何幫助或暗示讚賞

回答

0

我覺得invariant旨意爲你服務好這裏。首先,這可能是讓你知道,你可以嚴格哈克輸入一個密鑰樹:

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

(那一定是因爲cyclic shape definitions are sadly not allowed類)

我還沒有嘗試過,但type_structure s和Fred Emmott's TypeAssert看起來也有興趣。如果已知JSON blob的某些部分已修復,那麼可以使用invariant s隔離嵌套的不確定部分並從中構建一棵樹。在整個BLOB是未知的極限情況,那麼你可以切除TypeAssert因爲沒有有趣的固定結構斷言:

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); 
    } 
} 

沿着這條路走下去,你仍然必須補充的KeyedTreecontainsKey不變,但這是Hack中非結構化數據的現實。

+0

非常感謝您的意見! – Bearzi