如何将 json 数据从 android 应用程序发布到 Ruby on Rails 服务器



我正在尝试将json数据发送到我的RoR服务器,以便在服务器收到POST请求时创建一个新对象。我真的很陌生 RoR,所以我不确定如何正确设置它。

一段时间以来,我一直在这里搜索其他帖子,应用类似问题的解决方案,但我所做的似乎都不起作用。

在Rails方面 - 我专门为此设置了一条路线。

在路线中.rb

post '/api' => 'expenses#post_json_expense'

在expenses_controller.rb

# For creating an expense from the android app
def post_json_expense
Expense.new(expense_params)
end
# Never trust parameters from the scary internet, only allow the white list through.
def expense_params
params.require(:expense).permit(:user_id, :amount, :category, :description)
end

我还关闭了令牌身份验证,以防万一导致问题。

在配置/应用程序中

config.action_controller.allow_forgery_protection = false

在安卓方面,我正在使用 Volley 发送 POST 请求

private void saveExpense () {
// Build the URL
String url = "https://my-project-url.herokuapp.com/api";
Log.i("API_REQUEST", url);
EditText etAmount = findViewById(R.id.et_amount);
EditText etDescription = findViewById(R.id.et_description);
EditText etCategory = findViewById(R.id.et_category);
// Get values from the EditTexts
double amount = Double.parseDouble(etAmount.getText().toString());
String description = etDescription.getText().toString().trim();
String category = etCategory.getText().toString().trim();
// If something was entered into all of the fields
if (amount > 0 && !description.isEmpty() && !category.isEmpty()) {

// Convert field entries into a JSON object
JSONObject expenseData = new JSONObject();
JSONObject expenseObject = new JSONObject();
try {
expenseData.put("user_id", user_id);
expenseData.put("amount", amount);
expenseData.put("description", description);
expenseData.put("category", category);
expenseObject.put("expense", expenseData);

JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.PUT, url, expenseObject, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
Toast.makeText(EditExpenseActivity.this, "POST Successful", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(EditExpenseActivity.this, MainActivity.class);
startActivity(intent);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(EditExpenseActivity.this, "POST Unsuccessful", Toast.LENGTH_SHORT).show();
}
}) {
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
params.put("Content-Type", "application/json");
return params;
}
};
// Make the API request
RequestQueue queue = Volley.newRequestQueue(this);
queue.add(jsonObjectRequest);

}
}

每次尝试将数据发布到应用程序时,我都会收到错误响应。 我哪里出错了?我对rails很陌生,这是我第一次尝试构建API,所以我不确定我做错了什么。

欢迎来到 S.O.!

因此,这里有一些事情需要解决。首先,在控制器中:

# For creating an expense from the android app
def post_json_expense
Expense.new(expense_params)
end

因此,首先,在此处调用Expense.new只会创建一个新对象,但它不会将其持久保存到数据库中;您还需要调用save来执行此操作。

接下来,您不会将任何类型的响应返回给调用方。也许返回诸如新费用的 id 之类的内容是有序的,或者返回费用本身。我建议像这样构造调用:

# For creating an expense from the android app
def post_json_expense
expense = Expense.new(expense_params)
unless expense.save
# TODO: Return an error status with some useful details
# You can get some from expense.errors
return render status: 400, json: { error: true }
end
# Render a JSON representation of the expense on successful save
render json: expense.as_json
end

接下来,在客户端,您发送Content-type标头,这很好,但您也可以发送Accept标头,这为服务器提供了您希望接收回的内容的线索:

public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
params.put("Content-Type", "application/json");
params.put("Accept", "application/json");
return params;
}

最后,您已将该方法分配给服务器上的 POST 路由:

post '/api' => 'expenses#post_json_expense'

但是您从您的应用程序中将其称为 PUT:

JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.PUT, url, expenseObject, new Response.Listener<JSONObject>() {

因此,该 URL 上没有PUT路由,因此请求总是失败。

清理这些问题应该会让您获得成功的响应。

就个人而言,我发现使用像curl这样的简单实用程序通常有助于调试此类通信错误,当您不知道问题是应用程序端编码问题还是服务器端编码问题(或两者兼而有之)的错误时。你可以通过使用类似curl的东西来消除变量,你可以确信它有效,然后从那里进行调试。

希望这对您有所帮助!

最新更新