Posting JSON params from java to sinatra service

2020-05-08 07:50发布

I have an android app posting to my sinatra service. Earlier I was not able to read parameters on my sinatra service. However, after I set content type to "x-www-form-urlencoded". I was able to see params but not quite how I wanted. I am getting something this as my params of the request at my sinatra service.

{"{\"user\":{\"gender\":\"female\"},\"session_id\":\"7a13fd20-9ad9-45c2-b308-
8f390b4747f8\"}"=> nil, "splat"=>["update_profile.json"], "captures"=>["update_profile.json"]}

This is how I am making request from my app.

StringEntity se;                    
se = new StringEntity(getJsonObjectfromNameValueList(params.get_params(), "user");
se.setContentType("application/x-www-form-urlencoded");
postRequest.setEntity(se);



private JSONObject getJsonObjectfromNameValueList(ArrayList<NameValuePair> _params, String RootName) {
    JSONObject rootjsonObject = new JSONObject();
    JSONObject jsonObject = new JSONObject();

    if (_params != null) {
        if (!_params.isEmpty()) {
            for (NameValuePair p : _params) {
                try {
                    if (p.getName().equals(ApplicationFacade.SESSION_ID))
                        rootjsonObject.put((String) p.getName(), (String) p.getValue());
                    else
                        jsonObject.put((String) p.getName(), (String) p.getValue());
                } catch (JSONException e) {
                    e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                }
            }
        }
    }

    try {
        rootjsonObject.put(RootName, jsonObject);

    } catch (JSONException e) {
        e.printStackTrace();
    }
    return rootjsonObject;
}

I tried using the method given by:How to make a nested Json object in Java?

This is how I made my request using the method mentioned in the link.

public ArrayList<NameValuePair> getJsonObjectfromNameValueList(ArrayList<NameValuePair> _params, String RootName){
    ArrayList<NameValuePair> arrayList = new ArrayList<NameValuePair>();
    JSONObject jsonObject = new JSONObject();
    if (_params != null) {
        if (!_params.isEmpty()) {
            for (NameValuePair p : _params) {
                try {
                    if (p.getName().equals(ApplicationFacade.SESSION_ID))
                        arrayList.add(new BasicNameValuePair((String) p.getName(), (String) p.getValue()));
                    else
                        jsonObject.put((String) p.getName(), (String) p.getValue());
                } catch (JSONException e) {
                    e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                }
            }
        }
    }
    arrayList.add(new BasicNameValuePair(RootName, jsonObject.toString()));
    return arrayList;
}

The response I got after making the above change was this:

{"session_id"=>"958c7dee-f12c-49ec-ab0c-932e9a4ed173",
"user"=>"[gender=male]",
 "splat"=>["update_profile.json"],
 "captures"=>["update_profile.json"]}

Pretty close but that "gender=male" is not desirable. I need to pass these arguments to another service blindly, so I need to get them right.

The params that I want at my sinatra service are following.

{"session_id" : "958c7dee-f12c-49ec-ab0c-932e9a4ed173",
 "user": 
 {
   "gender" : "male"
 }

}

2条回答
The star\"
2楼-- · 2020-05-08 08:30

It turns out that the problem is with the way Sinatra gets its params. I was able to solve my problem using Kyle's awesome response to this post: Sinatra controller params method coming in empty on JSON post request

Code:

before do
  if request.request_method == "POST" and request.content_type=="application/json"
    body_parameters = request.body.read
    parsed = body_parameters && body_parameters.length >= 2 ? JSON.parse(body_parameters) : nil
    params.merge!(parsed)
  end
end

Alternate Method: However, I found a better solution to deal with it, by adding a middleware to do the same for me. I used rack-contrib gem. Following are the changes I did in my code:

EDIT:

use git to get the version where issue related to content type application/json;charset=UTF-8 is fixed

Gemfile:

gem 'rack-contrib', git: 'git@github.com:rack/rack-contrib', ref: 'b7237381e412852435d87100a37add67b2cfbb63'

config.ru:

use Rack::PostBodyContentTypeParser

source: http://jaywiggins.com/2010/03/using-rack-middleware-to-parse-json/

查看更多
聊天终结者
3楼-- · 2020-05-08 08:49

Using the following worked much better for me. I had to add request.body.rewind and :symbolize_names => true (while calling JSON.parse)

before do
  if request.request_method == "POST" and (request.content_type || '').include? "application/json" 
    request.body.rewind
    body_parameters = request.body.read
    parsed = body_parameters && body_parameters.length >= 2 ? JSON.parse(body_parameters, :symbolize_names => true) : nil
    params.merge!(parsed)
  end
end
查看更多
登录 后发表回答