xp-forge / json
读取和写入各种输入源中的JSON
v5.1.0
2024-03-24 11:41 UTC
Requires
- php: >=7.0.0
- xp-framework/core: ^12.0 | ^11.0 | ^10.0
Requires (Dev)
- xp-framework/test: ^2.0 | ^1.0
README
读取和写入各种输入源中的JSON。
示例
可以使用一个Input实现来从字符串中读取
// Strings $value= Json::read('"Test"'); // Input $in= new FileInput(new File('input.json')); $in= new StringInput('{"Hello": "World"}'); $in= new StreamInput(new SocketInputStream(...)); $value= Json::read($in);
可以写入字符串或使用一个Output实现
// Strings $json= Json::of('Test'); // Output $out= new FileOutput(new File('output.json')); $out= new StreamOutput(new SocketOuputStream(...)); Json::write($value, $out);
格式化输出
要更改输出格式,请将一个Format实例传递给输出构造函数。可用的格式有
DenseFormat($options):最适合网络I/O,没有无意义的空白,如果没有提供则默认,可以通过Format::dense($options= ~Format::ESCAPE_SLASHES)访问。WrappedFormat($indent, $options):包装第一级数组以及所有对象,在逗号和冒号后面使用空白。一个使用4个空格缩进且默认不转义正斜杠的此格式实例可以通过Format::wrapped($indent= " ", $options= ~Format::ESCAPE_SLASHES)访问。
可以组合使用以下选项
Format::ESCAPE_SLASHES:用""转义正斜杠 - 默认行为。Format::ESCAPE_UNICODE:用"\uXXXX"转义Unicode - 默认行为。Format::ESCAPE_ENTITIES:转义XML实体&、"、<和>。默认情况下,这些实体以它们的字面形式表示。
$out= new FileOutput(new File('glue.json'), Format::wrapped()); $out->write([ 'name' => 'example/package', 'version' => '1.0.0', 'require' => [ 'xp-forge/json' => '^3.0', 'xp-framework/core' => '^10.0' ] ]);
上面的代码将产生以下输出
{
"name": "example/package",
"version": "1.0.0'",
"require": {
"xp-forge/json": "^3.0",
"xp-framework/core": "^10.0"
}
}
顺序处理
顺序处理元素可以节省内存,并在某些情况下提供更好的性能。
读取
您可以使用elements()方法接收一个JSON数组的迭代器。它不会将整个源加载到内存中,然后返回解析后的数组;它会逐个解析数组元素,在遍历过程中产生它们。
$conn= new HttpConnection(...); $in= new StreamInput($conn->get('/search?q=example&limit=1000')->in()); foreach ($in->elements() as $element) { // Process }
如果您得到一个巨大的对象,您也可以使用pairs()方法顺序处理它。这将逐个解析单个键/值对。
$conn= new HttpConnection(...); $in= new StreamInput($conn->get('/resources/4711?expand=*')->in()); foreach ($in->pairs() as $key => $value) { // Process }
要检测流中的数据类型(同样,不读取它完全),您可以使用type()方法。
$conn= new HttpConnection(...); $in= new StreamInput($conn->get($resource)->in()); $type= $in->type(); if ($type->isArray()) { // Handle arrays } else if ($type->isObject()) { // Handle objects } else { // Handle primitives }
写入
要顺序写入数据,您可以使用begin()方法和它返回的流。当源提供一种顺序读取数据的方法时,这很有意义;如果您已经将整个数据放在内存中,使用write()会有相同的效果。
$query= $conn->query('select * from person'); $stream= (new StreamOutput(...))->begin(Types::$ARRAY); while ($record= $query->next()) { $stream->element($record); } $stream->close();
由于Stream类实现了Closeable接口,因此它可以用于with语句
$query= $conn->query('select * from person'); with ((new StreamOutput(...))->begin(Types::$ARRAY), function($stream) use($query) { while ($record= $query->next()) { $stream->element($record); } });
进一步阅读
- 性能数据。TL;DR:虽然比原生功能慢,但性能开销在毫秒范围内。使用顺序处理,我们在性能和内存方面都有优势。
- 解析JSON是一场灾难。此库在其自己的测试套件旁边运行此测试套件。

