在Hack严格模式下反序列化JSON

时间:2017-02-11 09:03:54

标签: hhvm hacklang

我有一个嵌套的JSON文件,由只有字符串的键和值组成。但是JSON文件的结构并不固定,因此有时它可以嵌套3个级别,有时只有2个级别。 我想知道我怎么能在严格模式下序列化这个?

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

}

如果我知道JSON的结构,我只是为它编写我自己的类,但由于键不是固定的,而且嵌套可能分为几个层次,我真的很想知道我是如何切割这样的将对象转换为特定类型。

任何帮助或提示赞赏

1 个答案:

答案 0 :(得分:1)

我认为invariant将在这里为您提供良好的服务。首先,知道你可以严格地在Hack中输入一个键控树可能会有所帮助:

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

在未来的道路上,您仍然必须在containsKey上补充KeyedTree不变量,但这是Hack中非结构化数据的现实。