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是一场灾难。此库在其自己的测试套件旁边运行此测试套件。