<div dir="ltr"><div dir="ltr"><div dir="ltr">I misread your email while walking :-D<div><br></div><div>You are right, the render call on the OpenAPI plugin requires you to feed it with a data structure that can be rendered as a JSON object. So what I'd loop on the results using fetch_hashref, and then do what is needed on each field (including mapping 1/0 into Mojo::JSON->true/Mojo::JSON->false if boolean, making integers really be integers, etc.</div><div><br></div><div><br></div></div></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">El lun., 20 may. 2019 a las 11:40, Stephen Graham (<<a href="mailto:s.graham4@herts.ac.uk">s.graham4@herts.ac.uk</a>>) escribió:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">





<div lang="EN-GB">
<div class="gmail-m_-8355064480052243263WordSection1">
<p class="MsoNormal"><span>Hi Tomas – the ability to extend the API with custom endpoints using the plugin system is a great Koha feature!
</span><span style="font-family:"Segoe UI Emoji",sans-serif">😊</span><span><u></u><u></u></span></p>
<p class="MsoNormal"><span><u></u> <u></u></span></p>
<p class="MsoNormal"><span>If I change my openapi.json to what you suggest I get:<u></u><u></u></span></p>
<p class="MsoNormal"><span><u></u> <u></u></span></p>
<p class="MsoNormal"><span>{"errors":[{"message":"Expected array - got string.","path":"\/"}],"status":500}<u></u><u></u></span></p>
<p class="MsoNormal"><span><u></u> <u></u></span></p>
<p class="MsoNormal"><span>, so I guess I need to pass my data to the render method as an array and not as a JSON string? If I do this I’m getting a can’t call method on unblessed refence error:<u></u><u></u></span></p>
<p class="MsoNormal"><span><u></u> <u></u></span></p>
<p class="MsoNormal"><span>my @n = map { ( $_->encode_json ) } @{$notices};<u></u><u></u></span></p>
<p class="MsoNormal"><span>return $c->render( status => 200, openapi => \@n );<u></u><u></u></span></p>
<p class="MsoNormal"><span><u></u> <u></u></span></p>
<p class="MsoNormal"><span>I guess because @{$notices} is an array of hashes? I see in the Patrons.pm REST module, that they are using a method called _<i>to</i>_api, which according to the Perl doc:<u></u><u></u></span></p>
<p class="MsoNormal"><span><u></u> <u></u></span></p>
<p class="MsoNormal"><span>“Helper function that maps unblessed Koha::Patron objects into REST api attribute names.”<u></u><u></u></span></p>
<p class="MsoNormal"><span><u></u> <u></u></span></p>
<p class="MsoNormal"><span>Sorry, it might be obvious, but do I need to iterate though my results and convert them into…. I’m not sure what really. Looking at the _<i>to</i>_api  method it just seems to be mapping the database
 column names to the API names, which I have done already in my initial sql query, and returns a Patron object. Should I be able to do what I want with the data structure I get from a
</span>fetchall_arrayref({})?<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">Cheers, Stephen<span><u></u><u></u></span></p>
<p class="MsoNormal"><span><u></u> <u></u></span></p>
<p class="MsoNormal"><span><u></u> <u></u></span></p>
<p class="MsoNormal"><b><span lang="EN-US">From:</span></b><span lang="EN-US"> Tomas Cohen Arazi <<a href="mailto:tomascohen@gmail.com" target="_blank">tomascohen@gmail.com</a>>
<br>
<b>Sent:</b> 20 May 2019 14:25<br>
<b>To:</b> Stephen Graham <<a href="mailto:s.graham4@herts.ac.uk" target="_blank">s.graham4@herts.ac.uk</a>><br>
<b>Cc:</b> koha-devel <<a href="mailto:koha-devel@lists.koha-community.org" target="_blank">koha-devel@lists.koha-community.org</a>><br>
<b>Subject:</b> Re: [Koha-devel] Restful API question<u></u><u></u></span></p>
<p class="MsoNormal"><u></u> <u></u></p>
<div>
<p class="MsoNormal">I think it should read like:<br>
<br>
"200": {<br>
    "description": "A list pending notifications",<br>
    "schema": {<br>
        "type": "array",<br>
        "items": {<br>
            "type": "object",<br>
            "properties": {<br>
                "userid": {<br>
                        "type": "string",<br>
                        "description": "Unique User ID"<br>
                },<br>
                ...<br>
            }<br>
        }<br>
    }<br>
}<br>
<br>
You can of course under-specify it, just saying you return JSON or the way you did it, just avoiding OpenAPI altogether, but you loose the ability for consumers to have a well documented API, and also you loose data validation (in and out), which is very important
 when implementing the API.<u></u><u></u></p>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">Happy to see others playing with this! Let me know how can I help1<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><br>
<br>
El lun., 20 may. 2019 a las 10:05, Stephen Graham (<<a href="mailto:s.graham4@herts.ac.uk" target="_blank">s.graham4@herts.ac.uk</a>>) escribió:<br>
><br>
> Hi Tomas – the below is what I have. When I do my sql select I’m doing:<br>
><br>
>  <br>
><br>
> select b.userid as userid,<br>
><br>
> mq.message_id as messageid,<br>
><br>
> mq.subject as subject,<br>
><br>
> mq.content as body<br>
><br>
>  <br>
><br>
> ,so the field names should map to the item names in the openapi.json. I’m just not sure what I should be passing to the render method, and how to describe that in the openapi.json file. At the moment I’m passing a string – it’s JSON – but just a string. Maybe
 that isn’t right? When I look to see how the Patrons API does it, it works like:<br>
><br>
>  <br>
><br>
> my @patrons = $patrons->as_list;<br>
><br>
> @patrons = map { _to_api( $_->TO_JSON ) } @patrons;<br>
><br>
> return $c->render( status => 200, openapi => \@patrons );<br>
><br>
>  <br>
><br>
> and then seems to say it’s an array of objects in their json files (patron.json and patron.json).<br>
><br>
>  <br>
><br>
> Here is my openapi.json file:<br>
><br>
>  <br>
><br>
> {<br>
><br>
>   "/notifications": {<br>
><br>
>     "get": {<br>
><br>
>       "x-mojo-to": "Uk::Ac::Herts::Notifications::NotificationController#getPendingNotices",<br>
><br>
>       "operationId": "PatronEmailNotice",<br>
><br>
>       "tags": ["notifications"],<br>
><br>
>       "produces": [<br>
><br>
>         "application/json"<br>
><br>
>       ],<br>
><br>
>       "responses": {<br>
><br>
>         "200": {<br>
><br>
>           "description": "A list of pending notices",<br>
><br>
>           "schema": {<br>
><br>
>                 "type": "array",<br>
><br>
>                 "items": {<br>
><br>
>                 "userid": {<br>
><br>
>                         "type": "string",<br>
><br>
>                         "description": "Unique User ID"<br>
><br>
>                 },<br>
><br>
>                 "messageid": {<br>
><br>
>                         "type": "string",<br>
><br>
>                         "description": "Unique Notice ID"<br>
><br>
>                 },<br>
><br>
>                 "subject": {<br>
><br>
>                         "type": "string",<br>
><br>
>                         "description": "Notice Subject"<br>
><br>
>                 },<br>
><br>
>                 "body": {<br>
><br>
>                         "type": "string",<br>
><br>
>                         "description": "Notice Body"<br>
><br>
>                 }<br>
><br>
>                 }<br>
><br>
>                 }<br>
><br>
>         },<br>
><br>
>         "404": {<br>
><br>
>           "description": "An error occured",<br>
><br>
>           "schema": {<br>
><br>
>               "type": "object",<br>
><br>
>                 "properties": {<br>
><br>
>                   "error": {<br>
><br>
>                     "description": "An explanation for the error",<br>
><br>
>                     "type": "string"<br>
><br>
>                   }<br>
><br>
>                 }<br>
><br>
>           }<br>
><br>
>         }<br>
><br>
>       },<br>
><br>
>       "x-koha-authorization": {<br>
><br>
>         "permissions": {<br>
><br>
>           "borrowers": "1"<br>
><br>
>         }<br>
><br>
>       }<br>
><br>
>     }<br>
><br>
>   }<br>
><br>
> }<br>
><br>
>  <br>
><br>
> From: Tomas Cohen Arazi <<a href="mailto:tomascohen@gmail.com" target="_blank">tomascohen@gmail.com</a>><br>
> Sent: 20 May 2019 12:28<br>
> To: Stephen Graham <<a href="mailto:s.graham4@herts.ac.uk" target="_blank">s.graham4@herts.ac.uk</a>><br>
> Cc: koha-devel <<a href="mailto:koha-devel@lists.koha-community.org" target="_blank">koha-devel@lists.koha-community.org</a>><br>
> Subject: Re: [Koha-devel] Restful API question<br>
><br>
>  <br>
><br>
> The most probable problem is the OpenAPI spec is wrong, and then the plugin API is skipped altogether.
<br>
><br>
>  <br>
><br>
> If possible, share the openapi.json file in your plugin<br>
><br>
>  <br>
><br>
> El lun., 20 de mayo de 2019 08:18, Stephen Graham <<a href="mailto:s.graham4@herts.ac.uk" target="_blank">s.graham4@herts.ac.uk</a>> escribió:<br>
><br>
> Hi all – I know it’s Kohacon this week so a lot of people will be busy there, but just in case ……… (also sorry for the length of the email!):<br>
><br>
>  <br>
><br>
> I testing creating a custom API endpoint using the Koha plugin system. I’ve been using the code in the Kitchen sink plugin as a template, and it seems to be working well apart from my lack of Swagger/OpenAPI knowledge – I think it’s this I struggling with.
 I have three files:<br>
><br>
>  <br>
><br>
> koha-dev/var/lib/plugins/Koha/Plugin/Uk/Ac/Herts/Notifications.pm<br>
><br>
> koha-dev/var/lib/plugins/Koha/Plugin/Uk/Ac/Herts/Notifications/NotificationController.pm<br>
><br>
> koha-dev/var/lib/plugins/Koha/Plugin/Uk/Ac/Herts/Notifications/openapi.json<br>
><br>
>  <br>
><br>
> The work is done in NotificationController.pm where I have a DBI call to get the following fields:<br>
><br>
>  <br>
><br>
> Borrower.userid<br>
><br>
> Message_queue.message_id<br>
><br>
> Message_queue.subject<br>
><br>
> Message_queue.content<br>
><br>
>  <br>
><br>
> I fetch the data, and convert into JSON (encode_json is a method from Mojo::JSON) like:<br>
><br>
>  <br>
><br>
> my $data = $sth->fetchall_arrayref({}); # return both fieldnames and values<br>
><br>
> my $json = encode_json($data);<br>
><br>
>  <br>
><br>
> if I then do (i.e. use text):<br>
><br>
>  <br>
><br>
> return $c->render( status => 200, text => $json)<br>
><br>
>  <br>
><br>
> it works fine. If I call <a href="https://herttest-staff.koha-ptfs.co.uk/api/v1/contrib/UH/notifications" target="_blank">
https://herttest-staff.koha-ptfs.co.uk/api/v1/contrib/UH/notifications</a> I get json like:<br>
><br>
>  <br>
><br>
> [ {<br>
><br>
>                “body”: “blah blah”,<br>
><br>
>                “messageid”: “1234567”,<br>
><br>
>                “subject”: “Important…”,<br>
><br>
>                “userid”:  99999999”<br>
><br>
> } {<br>
><br>
>                Etc etc<br>
><br>
> }]<br>
><br>
>  <br>
><br>
> So in Perl terms it’s an array of hashes. Which is what I want. However, if I try and use the openapi way that all the current “official” Koha endpoints use e.g.<br>
><br>
>  <br>
><br>
> return $c->render( status => 200, openapi => { notices => $json } );<br>
><br>
>  <br>
><br>
> it just doesn’t work. I have tried to map the field names with the appropriate types in openapi.json. I’ve tried object type with properties e.g.<br>
><br>
>  <br>
><br>
> "responses": {<br>
><br>
>         "200": {<br>
><br>
>           "description": "A list of pending notices",<br>
><br>
>           "schema": {<br>
><br>
>                 "type": "object",<br>
><br>
>                 "properties": {<br>
><br>
>                 "userid": {<br>
><br>
>                         "type": "string",<br>
><br>
>                         "description": "Unique User ID"<br>
><br>
>                 }, etc<br>
><br>
>  <br>
><br>
> , and I’ve tried array type with items:<br>
><br>
>  <br>
><br>
> "responses": {<br>
><br>
>         "200": {<br>
><br>
>           "description": "A list of pending notices",<br>
><br>
>           "schema": {<br>
><br>
>                 "type": "array",<br>
><br>
>                 "items": {<br>
><br>
>                 "userid": {<br>
><br>
>                         "type": "string",<br>
><br>
>                         "description": "Unique User ID"<br>
><br>
>                 }, etc<br>
><br>
>  <br>
><br>
> But I get a page not found error. When I pass my $json variable to the render method using openapi how do I get it to work? I’m happy to use the text way, but I want to understand where I’m going wrong. Any ideas, hints, tips would be most welcome!<br>
><br>
>  <br>
><br>
> Cheers, Stephen<br>
><br>
>  <br>
><br>
> --------------------------------------<br>
><br>
> Stephen Graham<br>
><br>
> Library Technology Consultant<br>
><br>
> Content and Collections Team<br>
><br>
> Library and Computing Services<br>
><br>
> University of Hertfordshire<br>
><br>
> Tel: 01707 286111<br>
><br>
> Ext: 77751<br>
><br>
> Email: <a href="mailto:s.graham4@herts.ac.uk" target="_blank">s.graham4@herts.ac.uk</a><br>
><br>
>  <br>
><br>
> _______________________________________________<br>
> Koha-devel mailing list<br>
> <a href="mailto:Koha-devel@lists.koha-community.org" target="_blank">Koha-devel@lists.koha-community.org</a><br>
> <a href="http://lists.koha-community.org/cgi-bin/mailman/listinfo/koha-devel" target="_blank">http://lists.koha-community.org/cgi-bin/mailman/listinfo/koha-devel</a><br>
> website : <a href="http://www.koha-community.org/" target="_blank">http://www.koha-community.org/</a><br>
> git : <a href="http://git.koha-community.org/" target="_blank">http://git.koha-community.org/</a><br>
> bugs : <a href="http://bugs.koha-community.org/" target="_blank">http://bugs.koha-community.org/</a><br>
<br>
<br>
<br>
--<br>
Tomás Cohen Arazi<br>
Theke Solutions (<a href="http://theke.io" target="_blank">http://theke.io</a>)<br>
<span style="font-family:"Segoe UI Symbol",sans-serif">✆</span> +54 9351 3513384<br>
GPG: B2F3C15F<u></u><u></u></p>
</div>
</div>
</div>
</div>

</blockquote></div><br clear="all"><div><br></div>-- <br><div dir="ltr" class="gmail_signature"><div dir="ltr"><div><div dir="ltr"><div style="font-size:12.8px">Tomás Cohen Arazi</div><div style="font-size:12.8px">Theke Solutions (<a href="http://theke.io/" target="_blank">http://theke.io</a>)<br>✆ +54 9351 3513384<br>GPG: B2F3C15F</div></div></div></div></div>