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 <[email protected]> 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 > [email protected] > Phone: +1 812-482-5224 > > Cell: +1 812-630-7622 > www.marklogic.com > > > > *From:* [email protected] [mailto: > [email protected]] *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 <[email protected]> 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 > [email protected] > Phone: +1 812-482-5224 > > Cell: +1 812-630-7622 > www.marklogic.com > > > > *From:* [email protected] [mailto: > [email protected]] *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 <[email protected]> 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 > [email protected] > Phone: +1 812-482-5224 > > Cell: +1 812-630-7622 > www.marklogic.com > > > > *From:* [email protected] [mailto: > [email protected]] *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:* [email protected] [ > [email protected]] on behalf of Indrajeet Verma [ > [email protected]] > *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 > [email protected] > Manage your subscription at: > http://developer.marklogic.com/mailman/listinfo/general > > > > > _______________________________________________ > General mailing list > [email protected] > Manage your subscription at: > http://developer.marklogic.com/mailman/listinfo/general > > > > _______________________________________________ > General mailing list > [email protected] > Manage your subscription at: > http://developer.marklogic.com/mailman/listinfo/general > >
_______________________________________________ General mailing list [email protected] Manage your subscription at: http://developer.marklogic.com/mailman/listinfo/general
