[basex-talk] JSON output in PHP client
I've been playing a bit with BaseX the last couple of days - and very excited about the product while doing so - but now I am having problems outputting JSON from a PHP script. I have this XQuery: declare option output:method json; declare option output:json format=jsonml; json type=object { for $user in collection(saveresult)//user[_id=1f2cda8f-a18a-44ba-8d17-73626d472306] return testResults testId{$user/test/_id}/testId grade{$user/user_info/user_grade}/grade /testResults } /json In the BaseX GUI this yields: [json, {type:object}, [testResults, [testId, [_id, Bio-1]], [grade, [user_grade, 7]]], [testResults, [testId, [_id, Bio-2]], [grade, [user_grade, 1 Which is what I expected after reading about the JSONML format. (Not too happy with that format, but that's another story). Running exactly the same XQuery form within a PHP script however yields this: json type=object testResults testId _idBio-1/_id /testId grade user_grade7/user_grade /grade /testResults testResults testId _idBio-2/_id /testId grade user_grade1/user_grade /grade /testResults /json (script is attached; note that the $ signs have been escaped there so that PHP will not try to evaluate them) In other words, the result is being output as XML with an enclosing json root tag, not as JSON. What is happening here? And how can I have BaseX return JSON from PHP? Paul Swennenhuis ?php /* * This example shows how queries can be executed in an iterative manner. * Documentation: http://basex.org/api * * (C) BaseX Team 2005-11, BSD License */ include(BaseXClient.php); try { // create session $session = new Session(localhost, 1984, admin, a33445); try { // create query instance // make sure to escape $ signs! $input = XQ declare option output:json format=jsonml; json type=object { for \$user in collection(saveresult)//user[_id=1f2cda8f-a18a-44ba-8d17-73626d472306] return testResult testId{\$user/test/_id}/testId grade{\$user/user_info/user_grade}/grade /testResult } /json XQ; //print $input; $query = $session-query($input); // bind variable //$query-bind($name, number); print $query-execute().\n; // close query instance $query-close(); } catch (Exception $e) { // print exception print $e-getMessage(); } // close session $session-close(); } catch (Exception $e) { // print exception print $e-getMessage(); } ?
Re: [basex-talk] JSON output in PHP client
Hi Paul, Which is what I expected after reading about the JSONML format. (Not too happy with that format, but that's another story). I agree; JSONML is a quasi-standard we have adopted, which is mainly useful for converting arbitrary XML to JSON. If you can decide how your XML format looks like, I would recommend the standard conversion format: declare option output:method json; json type=array objects='_'{ for $user in collection(saveresult)//user[_id=1f2cda8f-a18a-44ba-8d17-73626d472306] return testResults testId{$user/test/_id}/testId grade{$user/user_info/user_grade}/grade /testResults }/json Running exactly the same XQuery form within a PHP script however yields this: The query results are currently sent to all clients in their standard format (i.e., ignoring all serialization parameters). That's why you'll need to convert your JSON within XQuery: json:serialize( json type=array objects='_'{ ... }/json ) If I remember what was the reason for that design decision, I'll give you an update soon.. Hope this helps, Christian
Re: [basex-talk] JSON output in PHP client
Hi Christian, Thanks for the quick answer. Unfortunately your proposed solution (json:serialize) does not work in this case; BaseX returns a BXJS0002 error: JSON serializer: found, _ expected. The modified query reads: json:serialize( json type=array objects='_'{ for \$user in collection(saveresult)//user[_id=1f2cda8f-a18a-44ba-8d17-73626d472306] return testResult testId{\$user/test/_id}/testId grade{\$user/user_info/user_grade}/grade /testResult } /json ) Paul Hi Paul, Which is what I expected after reading about the JSONML format. (Not too happy with that format, but that's another story). I agree; JSONML is a quasi-standard we have adopted, which is mainly useful for converting arbitrary XML to JSON. If you can decide how your XML format looks like, I would recommend the standard conversion format: declare option output:method json; json type=array objects='_'{ for $user in collection(saveresult)//user[_id=1f2cda8f-a18a-44ba-8d17-73626d472306] return testResults testId{$user/test/_id}/testId grade{$user/user_info/user_grade}/grade /testResults }/json Running exactly the same XQuery form within a PHP script however yields this: The query results are currently sent to all clients in their standard format (i.e., ignoring all serialization parameters). That's why you'll need to convert your JSON within XQuery: json:serialize( json type=array objects='_'{ ... }/json ) If I remember what was the reason for that design decision, I'll give you an update soon.. Hope this helps, Christian
Re: [basex-talk] JSON output in PHP client
I should have run your query before sending you an answer. The following query should work: json:serialize( json type=array objects='_'{ for $user in collection(saveresult)//user[_id=1f2cda8f-a18a-44ba-8d17-73626d472306] return _ testId{$user/test/_id}/testId grade{$user/user_info/user_grade}/grade /_ }/json ) Which is what I expected after reading about the JSONML format. (Not too happy with that format, but that's another story). I agree; JSONML is a quasi-standard we have adopted, which is mainly useful for converting arbitrary XML to JSON. If you can decide how your XML format looks like, I would recommend the standard conversion format: declare option output:method json; json type=array objects='_'{ for $user in collection(saveresult)//user[_id=1f2cda8f-a18a-44ba-8d17-73626d472306] return testResults testId{$user/test/_id}/testId grade{$user/user_info/user_grade}/grade /testResults }/json Running exactly the same XQuery form within a PHP script however yields this: The query results are currently sent to all clients in their standard format (i.e., ignoring all serialization parameters). That's why you'll need to convert your JSON within XQuery: json:serialize( json type=array objects='_'{ ... }/json ) If I remember what was the reason for that design decision, I'll give you an update soon.. Hope this helps, Christian
Re: [basex-talk] JSON output in PHP client
Still no luck: JSON serializer: testId is typed as string and cannot be nested I think I am going to move the JSON conversion to within PHP or Javascript, and keep the XQueries clean and readable. Paul json:serialize( json type=array objects='_'{ for $user in collection(saveresult)//user[_id=1f2cda8f-a18a-44ba-8d17-73626d472306] return _ testId{$user/test/_id}/testId grade{$user/user_info/user_grade}/grade /_ }/json )
Re: [basex-talk] JSON output in PHP client
Hi Paul, no need to despair ;) The default JSON converter is the direct one (which would require testId/ to be declared an object), not JsonML. If you you want to use JsonML you can do so by using json:serialize( json type=array objects='_'{ for $user in collection(saveresult)//user[_id=1f2cda8f-a18a-44ba-8d17-73626d472306] return _ testId{$user/test/_id}/testId grade{$user/user_info/user_grade}/grade /_ }/json, map { 'format': 'jsonml' } ) For some more information you can take a look at https://docs.basex.org/wiki/JSON_Module Cheers, Dirk On 11/07/14 12:13, Paul Swennenhuis wrote: Still no luck: JSON serializer: testId is typed as string and cannot be nested I think I am going to move the JSON conversion to within PHP or Javascript, and keep the XQueries clean and readable. Paul json:serialize( json type=array objects='_'{ for $user in collection(saveresult)//user[_id=1f2cda8f-a18a-44ba-8d17-73626d472306] return _ testId{$user/test/_id}/testId grade{$user/user_info/user_grade}/grade /_ }/json ) -- Dirk Kirsten, BaseX GmbH, http://basex.org |-- Firmensitz: Blarerstrasse 56, 78462 Konstanz |-- Registergericht Freiburg, HRB: 708285, Geschäftsführer: | Dr. Christian Grün, Dr. Alexander Holupirek, Michael Seiferle `-- Phone: 0049 7531 28 28 676, Fax: 0049 7531 20 05 22
Re: [basex-talk] JSON output in PHP client
Ah, yes, that did the trick. I read about the options but had forgotten about it. Thanks. I will run some performance tests to decide for json:serialize or PHP internal conversion which might be considerably slower. Paul json:serialize( json type=array objects='_'{ for $user in collection(saveresult)//user[_id=1f2cda8f-a18a-44ba-8d17-73626d472306] return _ testId{$user/test/_id}/testId grade{$user/user_info/user_grade}/grade /_ }/json, map { 'format': 'jsonml' } )
Re: [basex-talk] JSON output in PHP client
Hi Paul, and thanks Dirk. One last note: If you plan to stick with JsonML, you can serialize arbitrary XML data, such as.. json:serialize( xml{ for $user in collection(saveresult)//user[_id=1f2cda8f-a18a-44ba-8d17-73626d472306] return result testId{$user/test/_id}/testId grade{$user/user_info/user_grade}/grade /result }/xml, map { 'format': 'jsonml' } ) C. On Fri, Jul 11, 2014 at 12:48 PM, Paul Swennenhuis p...@swennenhuis.nl wrote: Ah, yes, that did the trick. I read about the options but had forgotten about it. Thanks. I will run some performance tests to decide for json:serialize or PHP internal conversion which might be considerably slower. Paul json:serialize( json type=array objects='_'{ for $user in collection(saveresult)//user[_id=1f2cda8f-a18a-44ba-8d17-73626d472306] return _ testId{$user/test/_id}/testId grade{$user/user_info/user_grade}/grade /_ }/json, map { 'format': 'jsonml' } )