Hi David, I have modified the condition like below in router.xqy itself from where data is being set in map:map and now this is working fine without changing in the code above. Hope this should be fine and better solution :)
else if (xdmp:get-request-body()/node() instance of object-node()) then xdmp:to-json(xdmp:get-request-body()/node())/node() else () Complete condition in router.xqy- if (fn:exists(xdmp:get-request-body())) then ( map:put($req:request, "req-body", if (xdmp:get-request-body()/node() instance of element()) then xdmp:get-request-body()/node() else if (xdmp:get-request-body()/node() instance of text()) then xdmp:quote(xdmp:get-request-body()/node()) else if (xdmp:get-request-body()/node() instance of object-node()) then xdmp:to-json(xdmp:get-request-body()/node())/node() else () ) ) On Tue, May 5, 2015 at 2:22 PM, Indrajeet Verma <indrajeet.ve...@gmail.com> wrote: > Hi David, > > Thank you for explaining all the things. I went through the documentation > that you have shared with me again. > > What I understand, my code could be fixed in following two ways, > > 1. First convert JOSN object to string format however the jsonLib:parse() > is not accepting the value that returns from xdmp:to-json($params)/node(). > It says, this is not a string and If I apply xdmp:quote(), this starts > working with existing code that requires xs:string as input. The > json:transform-to-json() > is not working however logically this should as based on the documentation, > this also returns xs:string and take json as object. I want input json as > xs:string for my function. > > let $params := xdmp:get-request-body() > let $json := xdmp:to-json($params)/node() > let $json := try{ jsonLib:parse(xdmp:quote($json)) } catch ($e) > {xdmp:log($json)} (: doing xdmp:quote() is strange here as > xdmp:to-json()/node() returns string itself.:) > > 2. Using ML8 function and wrapping the result with in <json> that requires > for my API code. > > let $params := xdmp:get-request-body() > let $custom := > let $config := json:config("custom") > return > ( > map:put($config, "element-namespace", " > http://marklogic.com/json"), > $config > ) > let $json := try{ (json:transform-from-json($params, $custom)) } catch > ($e) {()} > let $json := <json type="object" xmlns="http://marklogic.com/json > ">{$json}</json> > > > The json functions those requires xs:string to convert into my APP > specific output. > > declare function json:parse( > $json as xs:string, > $enableExtensions as xs:boolean > ) as element(json:json) > { > let $test := if($isSupported) then () else > error(xs:QName("json:UNSUPPORTED"), "The JSON library isn't supported under > this version of MarkLogic, upgrade to 4.2 or later") > let $tokens := json:tokenize($json) > let $value := json:parseValue($tokens, 1, (), $enableExtensions) > let $test := > if(xs:integer($value/@position) != count($tokens) + 1) > then json:outputError($tokens, xs:integer($value/@position), > "Unhandled tokens") > else () > return <json:json>{ $value/(@type, @boolean), $value/node() > }</json:json> > }; > > declare function json:parse( > $json as xs:string > ) as element(json:json) > { > json:parse($json, true()) > }; > > Please advise if I am doing wrong thing. > > Regards, > Indrajeet > > > On Tue, May 5, 2015 at 4:17 AM, David Lee <david....@marklogic.com> wrote: > >> I will start you in the right direction ... >> >> XDMP-AS: (err:XPTY0004) $json as element(json:json) -- Invalid coercion: >> <error:error xsi:schemaLocation="http://marklogic.com/xdmp/error >> error.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >> xmlns:error="http://marklogic.com/xdmp/error"><error:code>XDMP-AS</error:code><error:name>err:XPTY0004</error:...</error:error> >> as element(json:json) >> >> >> >> >> >> This is explained in the compatibilty doc, I suggest you start there. >> Most of the internal JSON API's have changed signatures to use the native >> JSON nodes - this requires app level changes. >> >> >> >> https://docs.marklogic.com/guide/relnotes/chap4 >> >> >> >> See: >> >> https://docs.marklogic.com/guide/relnotes/chap4#id_94947 >> >> " The json:transform-to-json >> <https://docs.marklogic.com/json:transform-to-json> function uses >> xdmp:to-json <https://docs.marklogic.com/xdmp:to-json>, so it also >> returns a document-node() in MarkLogic 8" >> >> >> >> The error below are to be expected as a side effect of this. >> >> >> >> Any pre V8 code that uses the marklogic JSON functions is likely to need >> changing - That change may percolate up the API Layer - or it can be >> issolated within the function/api to expose the same signatures as before - >> which is best depends on your use case - but in any case its going to take >> some work. The actual changes can be very simple in most cases - it is >> quite easy to convert between representations, most of the work is design - >> where do you want to make the changes, is it better to hide them as much as >> possible or to convert to the native JSON data model. There are advantages >> to both. >> >> But it starts by reading the above docs, and then looking at your code >> and any dependent code to make the right choices for you. >> >> >> >> >> >> >> ----------------------------------------------------------------------------- >> >> David Lee >> Lead Engineer >> *Mark**Logic* Corporation >> d...@marklogic.com >> Phone: +1 812-482-5224 >> >> Cell: +1 812-630-7622 >> www.marklogic.com >> >> >> >> *From:* general-boun...@developer.marklogic.com [mailto: >> general-boun...@developer.marklogic.com] *On Behalf Of *Indrajeet Verma >> *Sent:* Monday, May 04, 2015 1:35 PM >> *To:* MarkLogic Developer Discussion >> *Subject:* Re: [MarkLogic Dev General] json namespace changes in >> json:transform-from-json($input) >> >> >> >> Hi David, >> >> >> >> Thank you for your explanation and help! >> >> >> >> 1. Could you explain what issues you are having ? >> >> >> >> XDMP-AS: (err:XPTY0004) $json as element(json:json) -- Invalid coercion: >> <error:error xsi:schemaLocation="http://marklogic.com/xdmp/error >> error.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >> xmlns:error="http://marklogic.com/xdmp/error"><error:code>XDMP-AS</error:code><error:name>err:XPTY0004</error:...</error:error> >> as element(json:json) >> >> >> >> Code in save() >> >> let $json := try{ jsonLib:parse(map:get($req-map, "req-body") ) } catch >> ($e) {($e)} >> >> >> >> 2. Where is this document used ? >> >> This saved document is being used to show user history. >> >> >> >> 3. Could you show the XQuery code that uses it? >> >> Please refer the code below. >> >> >> >> 4. What is not working, what you expected vs what you are getting etc. >> >> let $json := try{ jsonLib:parse(map:get($req-map, "req-body") ) } catch >> ($e) {($e)} >> >> >> >> I am expecting json:json however this is not coming. see below error. >> >> <error:format-string>XDMP-AS: (err:XPTY0004) $json as xs:string -- >> Invalid coercion: json:object(<json:object xmlns:xs=" >> http://www.w3.org/2001/XMLSchema" xmlns:xsi=" >> http://www.w3.org/2001/XMLSchema-instance" xmlns:json=" >> http://marklogic.com/xdmp/json"><json:entry >> key="docTitle"><json:value>histories: Search for >> app...</json:object>) as xs:string</error:format-string> >> >> >> >> One thing if you see, this seems a namespace mismatch issue. The >> namespace in the converted output is "http://marklogic.com/xdmp/json" >> however this expects http://marklogic.com/json. I thing roxy is playing >> major role here in upgrading ML8. I am going to open a ticket in roxy as >> well for this. >> >> >> >> This "http://marklogic.com/json" is being used by roxy to handle >> json.This namespace is in data model as well and index are also with same >> namespace. So if I will modify this namespace, Might be, the complete code >> repository require changes:). >> >> >> >> Actually I need to upgrade ML6 to ML8 without changing in UI & data model. >> >> >> >> I am sending you the code for your reference however what I have observed >> while upgrading, wherever the JSON is being used in the request body for >> creating files in the DB, everywhere the issues are coming. >> >> >> >> So the JSON format that is being sent in the request body in ML6 is not >> compatible with ML8 any more. I am not sure , is this roxy issue or the >> logic that has been written in the modules. >> >> >> >> >> >> declare function res:save( $type, $prefix) >> >> { >> >> try { >> >> >> >> invoke:invoke( >> >> "save", >> >> "http://marklogic.com/roxy/models/user/resources", >> >> "/app/lib/user-resources.xqy", >> >> ( >> >> auth:userName(), >> >> auth:userDirectory(), >> >> $type, >> >> $prefix, >> >> $req:request >> >> ), >> >> fn:false(), >> >> $cfg:RESOURCE-DB >> >> ) >> >> } catch ($e) {xdmp:log($e)} >> >> }; >> >> >> >> declare function res:save( $user-id, $root, $type, $prefix, $map) >> >> { >> >> let $doc := >> >> element resource { >> >> attribute wk-pid {fn:concat($prefix,"-", >> tools:generate-uuid-v4())}, >> >> element docType {$type}, >> >> element ownerId {$user-id}, >> >> element created {fn:current-dateTime()} >> >> } >> >> return >> >> ( >> >> res:_save( >> >> fn:concat($root,"/", $doc/docType, "/", $doc/@wk-pid,".xml"), >> >> $doc, >> >> $map >> >> ) >> >> ) >> >> }; >> >> >> >> (: ERROR IS COMING BELOW LINES >> >> let $json := try{ jsonLib:parse(map:get($req-map, "req-body") ) } catch >> ($e) {()} >> >> let $searchParameter := srch:json-search-params($json) >> >> :) >> >> declare function res:_save( $uri, $doc, $map ) >> >> { >> >> (:Working in ML6:) >> >> let $req-map := map:map($map) >> >> let $json := try{ jsonLib:parse(map:get($req-map, "req-body") ) } catch >> ($e) {()} >> >> let $searchParameter := srch:json-search-params($json) >> >> (: >> >> I am writing to support ML8 >> >> let $params := xdmp:get-request-body() >> >> let $custom := >> >> let $config := jsonl:config("custom") >> >> return >> >> ( >> >> map:put($config, "element-namespace", " >> http://marklogic.com/json"), >> >> $config >> >> ) >> >> let $json := try{ (jsonl:transform-from-json($params, $custom)) } catch >> ($e) {()} >> >> let $json := <json type="object" xmlns="http://marklogic.com/json >> ">{$json}</json> >> >> :) >> >> >> >> let $update := >> >> element resource { >> >> $doc/@*, >> >> $doc/docType, >> >> element docTitle {xs:string((map:get($req-map,"docTitle"), >> $json/json:docTitle, >> fn:concat($doc/docType,"-",fn:current-dateTime()))[1])}, >> >> $doc/ownerId, >> >> $doc/created, >> >> element modified {fn:current-dateTime()}, >> >> element shared {}, >> >> element parameter { >> >> for $node in $json/element()[fn:local-name(.) = >> ('type','contentColletion','source')] >> >> return >> >> element {fn:local-name($node)} { >> >> $node/fn:string() >> >> } >> >> }, >> >> if ($searchParameter) then >> >> ( >> >> (: $searchParameter :) >> >> (: element cts-query >> {search:parse($searchParameter/queryText/fn:string(), $cfg:SEARCH-OPTIONS)} >> :) >> >> >> >> (:ticket 4885: save-query process extract contentCollectionId >> :) >> >> if($searchParameter/element()[fn:local-name(.) >> ='contentCollection']) >> >> then ( >> >> element contentCollectionId >> {res:extractCollectionId($doc/ownerId,$searchParameter/element()[fn:local-name(.) >> ='contentCollection']/fn:string())} >> >> ) >> >> else () >> >> ) >> >> else (), >> >> element {fn:node-name($json)} { >> >> $json/@*, >> >> $json/node()[fn:not(fn:local-name(.) = >> ("docUrl","docId","docTitle","created","modified"))] >> >> } >> >> } >> >> return ( >> >> $update, >> >> tools:invoke("document-insert", >> >> ( >> >> $uri, >> >> $update >> >> ), >> >> $cfg:RESOURCE-DB >> >> ) >> >> )[1] >> >> }; >> >> >> >> (:~ >> >> : Converts incoming JSON structure into internal search parameter >> structure. >> >> : It will be stored into user resources and used for query construction. >> >> :) >> >> declare function m:json-search-params( $json as element(json:json)) >> >> as element (searchParameter)? >> >> { >> >> if ($json/json:searchParameter) then >> >> element searchParameter { >> >> for $item in $json/json:searchParameter/* >> >> where $item/@type != 'object' >> >> return >> >> element {fn:local-name($item)} { >> >> if ($item/@type = 'array') then ( >> >> for $value in $item/json:item[fn:not(@type = >> ('object','array'))] >> >> return >> >> element value { >> >> attribute type {if ($value/@type = "number") then >> "xs:unsignedLong" else "xs:string"}, >> >> $value/text() >> >> } >> >> ) else ( >> >> attribute type {if ($item/@type = "number") then >> "xs:unsignedLong" else "xs:string"}, >> >> $item/text() >> >> ) >> >> } >> >> } >> >> else >> >> () >> >> }; >> >> >> >> >> >> >> >> >> >> >> >> >> >> On Mon, May 4, 2015 at 9:44 PM, David Lee <david....@marklogic.com> >> wrote: >> >> If those modules are custom modules (written by you or your team, not >> by marklogic or roxy), then yes this is the right place to ask. >> >> >> >> If you goal is to minimize client side changes - then you will need to >> modify your XQuery code wherever V6 vs V8 compatibility has changed. >> >> >> >> Here is a good place to start in order to identify potential changes >> needed. >> >> >> >> https://docs.marklogic.com/guide/relnotes/chap4 >> >> >> >> I am not familiar with where this element would be used by a ML API >> >> <json type="object" xmlns="http://marklogic.com/json"> >> >> >> >> That is neither directly compatible with V6,7 or 8 'basic' JSON format, >> >> nor is it the namespace or format for a ML server side API that I am >> aware of. >> >> >> >> In the original question regarding use of xml:transform-to-xml , in >> general >> >> what you are doing is correct - the JSON is being translated to XML to >> the extent >> >> you describe you wanted. >> >> Since you don't reference exactly what it is that you are having problems >> with, its hard to guess ... >> >> Could you explain what issues you are having ? >> >> Where is this document used ? >> >> could you show the XQuery code that uses it? >> >> What is not working, what you expected vs what you are getting etc. >> >> >> >> >> >> >> ----------------------------------------------------------------------------- >> >> David Lee >> Lead Engineer >> *Mark**Logic* Corporation >> d...@marklogic.com >> Phone: +1 812-482-5224 >> >> Cell: +1 812-630-7622 >> www.marklogic.com >> >> >> >> *From:* general-boun...@developer.marklogic.com [mailto: >> general-boun...@developer.marklogic.com] *On Behalf Of *Indrajeet Verma >> *Sent:* Monday, May 04, 2015 11:48 AM >> >> >> *To:* MarkLogic Developer Discussion >> *Subject:* Re: [MarkLogic Dev General] json namespace changes in >> json:transform-from-json($input) >> >> >> >> Hi David, >> >> >> >> Might be I am wrong here and I will raise a ticket in roxy as well >> however in this case roxy is sending the request body same as it receives >> from the request. >> >> >> >> The manipulation and transformation logic is happening inside modules and >> that by using ML server functions. >> >> >> >> Regards, >> >> Indy >> >> >> >> >> >> On Mon, May 4, 2015 at 9:12 PM, David Lee <david....@marklogic.com> >> wrote: >> >> You mention Roxy. That adds another layer. I suggests the Roxy >> forum for discussing this. >> >> >> >> https://github.com/marklogic/roxy/issues >> >> >> >> Roxy is a community developed project, Not part of the core MarkLogic >> product. >> >> I don't know to what extent Roxy has been modified to work with ML8 or >> what changes to suggest to code using it. >> >> >> >> Many of the low level JSON related API's changed in ML8 and not all the >> community developed libraries have incorporated those yet. The Application >> APIs provided by MarkLogic (like the Java Client API, XCC etc) are updated >> in-sync with the server update releases, externally managed products and >> libraries are independently managed by their authors and/or the community >> (for OS projects). >> >> >> >> >> >> >> >> >> >> >> ----------------------------------------------------------------------------- >> >> David Lee >> Lead Engineer >> *Mark**Logic* Corporation >> d...@marklogic.com >> Phone: +1 812-482-5224 >> >> Cell: +1 812-630-7622 >> www.marklogic.com >> >> >> >> *From:* general-boun...@developer.marklogic.com [mailto: >> general-boun...@developer.marklogic.com] *On Behalf Of *Indrajeet Verma >> *Sent:* Monday, May 04, 2015 11:27 AM >> >> >> *To:* MarkLogic Developer Discussion >> *Subject:* Re: [MarkLogic Dev General] json namespace changes in >> json:transform-from-json($input) >> >> >> >> Thank you Eric and David for your response however our system is working >> fine in ML6 and details are, >> >> >> >> Same I wanted to achieve in ML8 without changing in UI and other search >> API that are being used for retrieval. >> >> >> >> Input request in body via roxy, >> >> >> >> { >> >> "docTitle": "histories: Search for apple", >> >> "type": "Search", >> >> "searchParameter": { >> >> "page": 1, >> >> "pageLength": 10, >> >> "queryText": "apple AND microsoft", >> >> "contentCollection": "All Content" >> >> } >> >> } >> >> >> >> Output that is being saved in ML, >> >> >> >> XML document <http://localhost:8000/qconsole/> >> >> <?xml version="1.0" encoding="UTF-8"?> >> >> <resource wk-pid="HIS-954e3f8f-2bbb-e79b-3747-7480b73db65b"> >> >> <docType> >> >> Histories >> >> </docType> >> >> <docTitle> >> >> histories: Search for apple >> >> </docTitle> >> >> <ownerId> >> >> USR-2fe944cc-013e-5b5a-0dba-7e98c3ffab00 >> >> </ownerId> >> >> <created> >> >> 2015-05-04T17:13:40.126+05:30 >> >> </created> >> >> <modified> >> >> 2015-05-04T17:13:40.126+05:30 >> >> </modified> >> >> <shared> >> >> </shared> >> >> <parameter> >> >> <type> >> >> Search >> >> </type> >> >> </parameter> >> >> <json type="object" xmlns="http://marklogic.com/json"> >> >> <type> >> >> Search >> >> </type> >> >> <searchParameter> >> >> <page> >> >> 1 >> >> </page> >> >> <pageLength> >> >> 10 >> >> </pageLength> >> >> <queryText> >> >> Apple AND microsoft >> >> </queryText> >> >> <contentCollection> >> >> All Content >> >> </contentCollection> >> >> </searchParameter> >> >> </json> >> >> </resource> >> >> >> >> >> >> >> >> On Mon, May 4, 2015 at 7:36 PM, David Lee <david....@marklogic.com> >> wrote: >> >> Erik addressed the most likely issue/question. >> >> As a follow-up , for clarification - >> >> your 2 examples are fundamentally different use cases of >> json:transform-to-xml() >> >> The first use (without the $config) is intended *only* for the pre-V8 >> use case of transforming >> >> arbitrary JSON into a 'black box' XML format with 100% fidelity. While >> it is a fairly readable format, >> >> Its not intended to be used directly - it is an implementation used by >> V7 before we had native JSON data types in the database. >> >> It is maintained for backwards compatibility for that use case only (if >> you have existing data in V7 format). >> >> >> >> The second example (with the 'custom' strategy and a $config) is not >> intended as a refinement or otherwise >> >> replacement for the first case. Its designed to allow for custom >> transformations between JSON and XML - >> >> possibly bi-directionally - at the expense of losing 100% fidelity. >> Many of these use cases are no longer necessary in V8 >> >> due to native support for JSON directly. >> >> >> >> It *can* be used as you have done - it should not be confused with the >> first case ( making any modifications >> >> at all to the 'basic' strategy transformation produces XML which will >> break any code expecting the V7 internal format), >> >> and I don't recommend it for API's that have a JSON interface - its much >> better to use that directly if possible. >> For API's that accept either JSON or XML - the formats for both are well >> defined - but the transformation between those formats >> can be very complex to get 100% right. So if you have JSON and using an >> API that accepts JSON - its much easier and better >> >> (and more efficient) to not attempt to transform it to XML. >> >> >> >> >> >> >> >> >> ----------------------------------------------------------------------------- >> >> David Lee >> Lead Engineer >> *Mark**Logic* Corporation >> d...@marklogic.com >> Phone: +1 812-482-5224 >> >> Cell: +1 812-630-7622 >> www.marklogic.com >> >> >> >> *From:* general-boun...@developer.marklogic.com [mailto: >> general-boun...@developer.marklogic.com] *On Behalf Of *Erik Hennum >> *Sent:* Monday, May 04, 2015 9:16 AM >> *To:* MarkLogic Developer Discussion >> *Subject:* Re: [MarkLogic Dev General] json namespace changes in >> json:transform-from-json($input) >> >> >> >> Hi, Indrajeet: >> >> In MarkLogic 8, you would typically store JSON directly as native JSON >> and not converted to XML. The direct approach will improve performance and >> maintainability. >> >> In the particular case, xdmp:unquote() will turn the input string into a >> JSON document that can be inserted into the database. >> >> The particular case looks like the input to a search request. Is there >> is a specific reason it must be encoded as XML? >> >> >> >> Erik Hennum >> ------------------------------ >> >> *From:* general-boun...@developer.marklogic.com [ >> general-boun...@developer.marklogic.com] on behalf of Indrajeet Verma [ >> indrajeet.ve...@gmail.com] >> *Sent:* Monday, May 04, 2015 6:00 AM >> *To:* MarkLogic Developer Discussion >> *Subject:* [MarkLogic Dev General] json namespace changes in >> json:transform-from-json($input) >> >> Hi, >> >> >> >> While upgrading ML6 to ML8, I needed to modify the JSON format and I did >> it based on my understanding on ML8 JSON handling however my senior is not >> convince with this solution so wanted to know if my approach is not best >> fit and could be better solution. >> >> >> >> Please someone take a look on my code and suggest any better solution? >> >> >> >> let $input := '{"docTitle":"histories: Search for apple", >> "type":"Search", "searchParameter":{"page":1, "pageLength":10}}' >> >> >> >> When I am using json:transform-from-json($input), getting below output >> with namespace "http://marklogic.com/xdmp/json/basic" >> >> <json type="object" xmlns="http://marklogic.com/xdmp/json/basic"> >> >> <docTitle type="string"> >> >> histories: Search for apple >> >> </docTitle> >> >> <type type="string"> >> >> Search >> >> </type> >> >> <searchParameter type="object"> >> >> <page type="number"> >> >> 1 >> >> </page> >> >> <pageLength type="number"> >> >> 10 >> >> </pageLength> >> >> </searchParameter> >> >> </json> >> >> >> >> However I wanted the results with the namespace " >> http://marklogic.com/json" so I have coded like below, >> >> >> >> let $custom := >> >> let $config := jsonl:config("custom") >> >> return >> >> ( >> >> map:put($config, "element-namespace", " >> http://marklogic.com/json"), >> >> $config >> >> ) >> >> let $json := try{ (jsonl:transform-from-json($input, $custom)) } catch >> ($e) {()} >> >> let $json := <json type="object" xmlns="http://marklogic.com/json >> ">{$json}</json> >> >> return $json >> >> >> >> *output:* >> >> <json type="object" xmlns="http://marklogic.com/json"> >> >> <docTitle> >> >> histories: Search for apple >> >> </docTitle> >> >> <type> >> >> Search >> >> </type> >> >> <searchParameter> >> >> <page> >> >> 1 >> >> </page> >> >> <pageLength> >> >> 10 >> >> </pageLength> >> >> </searchParameter> >> >> </json> >> >> >> >> Regards, >> >> Indy >> >> >> _______________________________________________ >> General mailing list >> General@developer.marklogic.com >> Manage your subscription at: >> http://developer.marklogic.com/mailman/listinfo/general >> >> >> >> >> _______________________________________________ >> General mailing list >> General@developer.marklogic.com >> Manage your subscription at: >> http://developer.marklogic.com/mailman/listinfo/general >> >> >> >> >> _______________________________________________ >> General mailing list >> General@developer.marklogic.com >> Manage your subscription at: >> http://developer.marklogic.com/mailman/listinfo/general >> >> >> >> _______________________________________________ >> General mailing list >> General@developer.marklogic.com >> Manage your subscription at: >> http://developer.marklogic.com/mailman/listinfo/general >> >> >
_______________________________________________ General mailing list General@developer.marklogic.com Manage your subscription at: http://developer.marklogic.com/mailman/listinfo/general