JSON output in PHP client

Friday, 11 July 2014 · 8 messages
PS
Paul Swennenhuis11 Jul 2014 10:21 #
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>
       <_id>Bio-1</_id>
     </testId>
     <grade>
       <user_grade>7</user_grade>
     </grade>
   </testResults>
   <testResults>
     <testId>
       <_id>Bio-2</_id>
     </testId>
     <grade>
       <user_grade>1</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
CG
Christian Grün11 Jul 2014 10:35 #
Hi Paul,
Quoted text · Paul Swennenhuis · 2 lines
> 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>
Quoted text · Paul Swennenhuis · 3 lines
> 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
PS
Paul Swennenhuis11 Jul 2014 11:17 #
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
Quoted text · Christian Grün · 42 lines
> 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 >
CG
Christian Grün11 Jul 2014 11:49 #
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>
)
Quoted text · Paul Swennenhuis · 41 lines
> >> 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 > >
PS
Paul Swennenhuis11 Jul 2014 12:13 #
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.
Quoted text · Christian Grün · 12 lines
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> > )
DK
Dirk Kirsten11 Jul 2014 12:41 #
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
Quoted text · Paul Swennenhuis · 21 lines
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
PS
Paul Swennenhuis11 Jul 2014 12:48 #
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.
Quoted text · Dirk Kirsten · 13 lines
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' } > )
CG
Christian Grün11 Jul 2014 14:54 #
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.
Quoted text · Paul Swennenhuis · 23 lines
On Fri, Jul 11, 2014 at 12:48 PM, Paul Swennenhuis <paul at 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' } >> ) > >

⚡Generated with XQuery