Kong / unirest-java

Unirest in Java: Simplified, lightweight HTTP client library.
http://kong.github.io/unirest-java/
MIT License
2.6k stars 592 forks source link

Param not recognized as Array #344

Closed luecking closed 4 years ago

luecking commented 4 years ago

I try to call

HttpResponse asJson = Unirest.get(baseUrl+"/data/Contact") .header("content-type","application/x-www-form-urlencoded") .header("Authorization", "Bearer " + accessToken) .queryString("fields", new String[] {"first_name", "last_name"} ) .asJson();

Answer from the server is: {"message":"Param fields should be of type Array","status":400}

To Reproduce

Expected behavior Should run

Screenshots

Environmental Data:

Is it possible to see more detailed errors or is there a known problem with arrays?

luecking commented 4 years ago

Verified it with latest release. Same error.

luecking commented 4 years ago

Maybe I'm following the totally wrong path. My problem is that the Rest-API is only described with some basic php code.

'$model = $client->model('Contact'); $fields = ['first_name', 'last_name']; $filters = ['first_name' => 'John']; $result = $model->getList(['fields' => $fields, 'filters' => $filters ], 0, 3); // fetch no more than 3 records, starting from the beginning printf("There are %d contacts in total\n", $result->totalResults()); echo json_encode($result->getRecords(), JSON_PRETTY_PRINT), "\n";'

Probably the problem is already the "$model->getList". Currently I've no idea how to translate it to unirest. Maybe you have an idea?

ryber commented 4 years ago

there is no overload of this method for arrays. So this gets consumed by .queryString(String name, Object value which ends up calling toString on whatever you pass into it. It doesn't know that the argument is an array (or any type in particular), so what is getting passed to your service is something like "[Ljava.lang.String;@73e9cf30"

If you want to pass multiple query params you have several options:

  1. You can pass a Collection which it does now about:
HttpResponse asJson = Unirest.get(baseUrl+"/data/Contact")
                       .header("content-type","application/x-www-form-urlencoded")
                       .header("Authorization", "Bearer " + accessToken)
                       .queryString("fields", Arrays.asList("first_name", "last_name"))
                       .asJson();

or pass them individually:

HttpResponse asJson = Unirest.get(baseUrl+"/data/Contact")
                       .header("content-type","application/x-www-form-urlencoded")
                       .header("Authorization", "Bearer " + accessToken)
                       .queryString("fields", "first_name" )
                       .queryString("fields", "last_name" )
                       .asJson();
luecking commented 4 years ago

I tested both. Always the same feedback from the server. What me wonders is the php request: $result = $model->getList(['fields' => $fields, 'filters' => $filters ], 0, 3);

In worst case, can I send somehow a complete Json String via the GET call?

ryber commented 4 years ago

I'm not a PHP person, it's not clear to me what "fields" are. The unirest code you are sending sends those params as query params, So you end up with

   /data/Contact?fields=first_name&fields=last_name

but it feels to me like they are looking for JSON on the model (the body) but a GET doesn't have a body. Are you sure they don't expect a post? You seem to be setting content-type, which is also not valid on a GET. If they want form fields you could try something like

Unirest.post("/data/Contact")
                .header("content-type","application/x-www-form-urlencoded")
                .header("Authorization", "Bearer " + "")
                .field("fields", Arrays.asList("first_name", "last_name"))
                .asJson();

or maybe they expect a json body like

JSONObject obj = new JSONObject()
                .put("fields", new JSONArray(Arrays.asList("first_name", "last_name")));

        Unirest.post("/data/Contact")
                .header("content-type","application/x-www-form-urlencoded")
                .header("Authorization", "Bearer " + "")
                .body(obj)
                .asJson();
luecking commented 4 years ago

I also assume that they expect a Json body. Your second example returns now '{"status":400,"message":"Param data is required"}'

Maybe the original data helps: http://1crm.github.io/1crm-api-client-php/ex-filter-contacts.html

ryber commented 4 years ago

without having a proper API spec (swagger or at least not PHP examples). You could go digging into that PHP client code. In any case the issue here is not that Unirest is doing anything wrong.

luecking commented 4 years ago

So, I totally agree. It is a documentation problem. The php code is not really providing good information. Just to bring it to an successful end. Maybe this helps in other projects.

The 1CRM provider sent me the relevant information 'https://demo.1crm.de/api.php/data/Account?fields[]=name&fields[]=is_supplier&filters[filter_text]=24'

I only tried to use instead of "fields" the keyword "fields[]". And it works now.

HttpResponse asJson = Unirest.get(baseUrl+"/data/Contact") .header("content-type","application/x-www-form-urlencoded") .header("Authorization", "Bearer " + accessToken) .queryString("fields[]", "first_name" ) .queryString("fields[]", "last_name" ) .asJson();

Thank you for your support. I really appreciate your work in the unirest library. Also thank you for that. Stay healthy.