Android Question REST API building string

ViMeAv ICT

Member
Licensed User
Longtime User
I want to do a httpJob to a rest api. This is the string I have to send:
send string:
 "name": "REST API TEST",
  "type": "simple",
  "regular_price": "21.99",
  "description": "Long description",
  "short_description": "Short description",
  "categories": [
    {
      "id": 9
    },
    {
      "id": 14
    }
  ],

I use this b4x code, the problem is the categories part, how can I past this in a map?
b4x code:
Sub Button1_Click
    

    Dim D As Map
    D.Initialize
    D.Put("name","REST API TEST")
    D.Put("type", "simple")
    D.Put("regular_price", "21.99")
    D.Put("description", "Long description")
    D.Put("short_description", "Short description")
    
    Dim A As Map
    A.Initialize
    A.Put("id", "9")
    A.Put("id", "14")
    D.Put("categories",A)
    
    
    Dim Job As HttpJob
    Job.Initialize("Register",Me)
    Job.Username = "?????????????????"
    Job.Password = "?????????????????????????????????"
    Job.PostMultipart("https://???????????????????/wp-json/wc/v3/products" , D,Null)
    Job.GetRequest.SetHeader("Content-Type", "application/json")
    Job.GetRequest.SetContentEncoding("text/plain")
    
End Sub

I get the following error:

ResponseError. Reason: , Response: {"code":"rest_invalid_param","message":"Ongeldige parameter(s): categories","data":{"status":400,"params":{"categories":"categories[0] wrong type object."},"details":{"categories":{"code":"rest_invalid_type","message":"categories[0] wrong type object.","data":{"param":"categories[0]"}}}}}

The problem is the map A, but I can't find out the correct syntax.
 

Alexander Stolte

Expert
Licensed User
Longtime User
I use this b4x code, the problem is the categories part, how can I past this in a map?
B4X:
    Dim D As Map
    D.Initialize
    D.Put("name","REST API TEST")
    D.Put("type", "simple")
    D.Put("regular_price", "21.99")
    D.Put("description", "Long description")
    D.Put("short_description", "Short description")
    
    Dim lst_Categories As List
    lst_Categories.Initialize
    lst_Categories.Add(CreateMap("id":9))
    lst_Categories.Add(CreateMap("id":14))

    D.Put("categories",lst_Categories)
    
    '**********Testing********************
    Dim json As JSONGenerator
    json.Initialize(D)
    Log(json.ToString)
 
Upvote 0

ViMeAv ICT

Member
Licensed User
Longtime User
The json seems alright, still getting same error:
error:
ResponseError. Reason: , Response: {"code":"rest_invalid_param","message":"
Invalid parameter(s): categories","data":{"status":400,"params":{"categories":"categories[0] wrong type object."},
"details":{"categories":{"code":"rest_invalid_type","message":"categories[0] wrong type object.","data":{"param":"categories[0]"}}}}}
 
Upvote 0

drgottjr

Expert
Licensed User
Longtime User
9 is not the same as "9". see if a. stolte's code works when you change 9 and 14 to "9" and "14". or check with server to see what it is it's expecting.
 
Upvote 0

bdunkleysmith

Active Member
Licensed User
Longtime User
Are you still posting

B4X:
Job.PostMultipart("https://???????????????????/wp-json/wc/v3/products" , D,Null)

I'm not sure why PostMultipart is required and so in addition to @Alexander Stolte's code I would try instead

B4X:
Job.PostString("https://???????????????????/wp-json/wc/v3/products" , json.ToString)
 
Upvote 0

ViMeAv ICT

Member
Licensed User
Longtime User
I tried with 9 en "9", no difference.
Just poststring json results in creating new product with default values, not my values.
Postmultipart, without categories, functions OK!
 
Upvote 0

bdunkleysmith

Active Member
Licensed User
Longtime User
Some thoughts:
  • @Alexander Stolte's code produces the JSON you requested and so can you point us to the REST API documentation so we can see if that reveals any clues?
  • Related to that, do you need to create the product categories first before you create a product with specified categories?
    To me this would account for why you get no error when you omit categories from your post. It appears to me that you may have to first create the categories you want which will return the category id which you can use in subsequent product creations.
  • When you say "Just poststring json results in creating new product with default values, not my values":
    • what "default values" do you see for that new product?
    • did you literally post "json" or "json.ToString"?
  • Posting the actual code here for each of your test cases would be useful because sometimes what we think we do is not actually what the code does and extra sets of eyes can assist.
 
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
Dim A As Map
A.Initialize
A.Put("id", "9")
A.Put("id", "14")
D.Put("categories",A)
categories must be a "List" of "Maps" based on the json in #1

B4X:
    Dim cl As List
    cl.initialze
    dim A as Map
    A.Initialize
    A.Put("id", "9")
    cl.Add(A)
    dim A as Map
    A.Initialize
    A.Put("id", "14")
    cl.Add(A)
    D.Put("categories",cl)

or simply

B4X:
    Dim cl As List
    cl.initialze
    cl.Add(CreateMap("id":"9")
    cl.Add(CreateMap("id":"14")
    D.Put("categories",cl)
 
Last edited:
Upvote 0

ViMeAv ICT

Member
Licensed User
Longtime User
  • Related to that, do you need to create the product categories first before you create a product with specified categories?
    To me this would account for why you get no error when you omit categories from your post. It appears to me that you may have to first create the categories you want which will return the category id which you can use in subsequent product creations.

    I use existing codes 71 (dog) en 72 (cat)

  • When you say "Just poststring json results in creating new product with default values, not my values":
    • what "default values" do you see for that new product?

      No description. short description, price, etc. Only "empty" article fields

    • did you literally post "json" or "json.ToString"?

      I tried both!
  • Posting the actual code here for each of your test cases would be useful because sometimes what we think we do is not actually what the code does and extra sets of eyes can assist.

    In visual basic code I use SetRequestHeader, I now only see GetRequestHeader.
 

Attachments

  • restapi.zip
    4.8 KB · Views: 141
Upvote 0

bdunkleysmith

Active Member
Licensed User
Longtime User
Thanks for your comprehensive answers @ViMeAv ICT.

I thought your Sub Button1_Click code was correct in that you post json.ToString rather than the map directly as you do in Sub Button2_Click given no error is returned and so don't know why that doesn't work. My only thought was that

B4X:
Job.GetRequest.SetHeader("Content-Type", "application/x-www-form-urlencoded")

should be replaced with

B4X:
job.GetRequest.SetContentType("application/json")

I've used B4X to access a variety of APIs, but I've not had experience with WooCommerce and so I created a free trial site to test code for myself. I found I needed to do the authentication differently because I was getting Unauthorised errors with the original method in your code. I got a hint from the documentation which said "Occasionally some servers may not parse the Authorization header correctly (if you see a "Consumer key is missing" error when authenticating over SSL, you have a server issue). In this case, you may provide the consumer key/secret as query string parameters instead."

So this code creates a new product with my own data and assigns it to a (existing) category successfully:

B4X:
    Job.Initialize("Register",Me)
    Job.Poststring("https://woo-speedily-eclectic-enemy.wpcomstaging.com/wp-json/wc/v3/products?consumer_key=ck_e00dxxxxxxxx&consumer_secret=cs_b2fexxxxxxx", json.ToString)
    Job.GetRequest.SetContentType("application/json")
    Log("button1 poststring")

{"id":64,"name":"REST API TEST4","slug":"rest-api-test4","permalink":"https:\/\/woo-speedily-eclectic-enemy.wpcomstaging.com\/product\/rest-api-test4\/","date_created":"2023-10-31T17:09:58","date_created_gmt":"2023-10-31T06:09:58","date_modified":"2023-10-31T17:09:58","date_modified_gmt":"2023-10-31T06:09:58","type":"simple","status":"publish","featured":false,"catalog_visibility":"visible","description":"Big Men's Item4","short_description":"BMI4","sku":"","price":"128.00","regular_price":"128.00","sale_price":"","date_on_sale_from":null,"date_on_sale_from_gmt":null,"date_on_sale_to":null,"date_on_sale_to_gmt":null,"on_sale":false,"purchasable":true,"total_sales":0,"virtual":false,"downloadable":false,"downloads":[],"download_limit":-1,"download_expiry":-1,"external_url":"","button_text":"","tax_status":"taxable","tax_class":"","manage_stock":false,"stock_quantity":null,"backorders":"no","backorders_allowed":false,"backordered":false,"low_stock_amount":null,"sold_individually":false,"weight":"","dimensions":{"length":"","width":"","height":""},"shipping_required":true,"shipping_taxable":true,"shipping_class":"","shipping_class_id":0,"reviews_allowed":true,"average_rating":"0","rating_count":0,"upsell_ids":[],"cross_sell_ids":[],"parent_id":0,"purchase_note":"","categories":[{"id":1374,"name":"Men","slug":"men"}],"tags":[],"images":[],"attributes":[],"default_attributes":[],"variations":[],"grouped_products":[],"menu_order":0,"price_html":"<span class=\"woocommerce-Price-amount amount\"><bdi><span class=\"woocommerce-Price-currencySymbol\">&#36;<\/span>128.00<\/bdi><\/span>","related_ids":[27,25,63,24,26],"meta_data":[{"id":397,"key":"_wpas_done_all","value":"1"}],"stock_status":"instock","has_options":false,"post_password":"","permalink_template":"https:\/\/woo-speedily-eclectic-enemy.wpcomstaging.com\/product\/%pagename%\/","generated_slug":"rest-api-test4","bundled_by":[],"bundle_stock_status":"instock","bundle_stock_quantity":null,"bundle_virtual":false,"bundle_layout":"","bundle_add_to_cart_form_location":"","bundle_editable_in_cart":false,"bundle_sold_individually_context":"","bundle_item_grouping":"","bundle_min_size":"","bundle_max_size":"","bundled_items":[],"bundle_sell_ids":[],"jetpack_publicize_connections":[],"jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"brands":[],"_links":{"self":[{"href":"https:\/\/woo-speedily-eclectic-enemy.wpcomstaging.com\/wp-json\/wc\/v3\/products\/64"}],"collection":[{"href":"https:\/\/woo-speedily-eclectic-enemy.wpcomstaging.com\/wp-json\/wc\/v3\/products"}]}}

1698734043322.png


Similarly, this returns a list of categories (NOTE: remove : job.GetRequest.SetContentType("application/json")):

B4X:
    Job.Initialize("Register",Me)
    Job.Download("https://woo-speedily-eclectic-enemy.wpcomstaging.com/wp-json/wc/v3/products/categories?consumer_key=ck_e00xxxxxxx&consumer_secret=cs_b2fexxxxxxx")
    Log("button1 poststring")

I should have said I tested the above code in B4J because it's more convenient for me than in B4A and so I hope the same applies in B4A for you.

UPDATE: I just tested in B4A and it works similarly successfully.
 
Last edited:
Upvote 0

ViMeAv ICT

Member
Licensed User
Longtime User
The replacement of the getrequest in button2_click fixed the job.
The button1_click with the map, instead of json, gives the error.
But no problem, I can use the button2_click option.
 
Upvote 0

bdunkleysmith

Active Member
Licensed User
Longtime User
The replacement of the getrequest in button2_click fixed the job.

I'm pleased you've got it working.

Strangely I can't get the PostMultipart version to work for my test site because when I include categories in the post it returns the error you reported in post #1: "categories[0] wrong type object." It seems that PostMultipart doesn't like a list within a map for me.

The button1_click with the map, instead of json, gives the error.

Yes the button1_click code using poststring won't work with the map because it requires a string, which in this case will be in JSON format (json.ToString).

Anyway, it has been an interesting mental exercise for me to learn about a new API.
 
Last edited:
Upvote 0
Top