将JSON对象数组的JSON对象发布到服务器

时间:2018-09-28 07:20:20

标签: android retrofit2

我正在尝试将JSON对象数组的JSON对象从我的android应用程序发送到服务器,但是它不起作用。我已经使用POSTMAN尝试过它,并且可以正常工作。以下是我尝试过的代码和json格式。

这是JSON格式

{
    "products": [
        {
            "product_id": 1,
            "product_name": "Smart Watch",
            "product_price": 99.99
        },

        {
            "product_id": 2,
            "product_name": "Smart TV",
            "product_price": 999.99
        }
    ]
}

这是POJO课

import com.google.gson.annotations.SerializedName;

public class Product {

    @SerializedName("product_id")
        public int productId;
        @SerializedName("product_name")
        public String productName;
        @SerializedName("product_price")
        public double productPrice;



    public Product(Integer productId, String productName, Float productPrice) {
        this.productId = productId;
        this.productName = productName;
        this.productPrice = productPrice;

    }

    public Integer getProductId() {
        return productId;
    }

    public void setProductId(Integer productId){
        this.productId = productId;
    }

    public String getproductName() {
        return productName;
    }

    public void setproductName(String productName) {
        this.productName = productName;
    }

    public String getproductPrice() {
        return productPrice;
    }

    public void setproductPrice(String productPrice) {
        this.productPrice = productPrice;
    }


}

这是我的ServiceGenerator类

public class ServiceGenerator {

    private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder();

    public static <S> S createService(Class<S> serviceClass, String baseUrl)
    {
        Retrofit builder = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .addConverterFactory(GsonConverterFactory.create())
                .client(httpClient.build())
                .build();

        return builder.create(serviceClass);
    }
}

添加了另一个类别的客户

public class Customers {
    @SerializedName("customers")
    public List<Customer> customers;

    public List<Customer> getCustomers() {
        return customers;
    }

    public void setCustomers(List<Customer> customers) {
        this.customers = customers;
    }
}

这是我的接口类

public interface IRetrofit {
    @Headers({

            "Accept: application/json",
            "Content-Type: application/json"
    })
    @POST("addproduct")
    Call<Products> postRawJSON(@Body Products products);


}

和我的MainActivity类

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
    public void onPostClicked(View view){

        // Using the Retrofit
        IRetrofit jsonPostService = ServiceGenerator.createService(IRetrofit.class, "http://192.168.122.1/productmanager/products/");


        Product product = new Products(null, "Samsung Galaxy A5", 234.54);
        Call<Product> call = jsonPostService.postRawJSON(product);
        call.enqueue(new Callback<Product>() {

            @Override
            public void onResponse(Call<Product> call, Response<Product> response) {
                try{
                    Log.e("response-success", response.body().toString());
                }catch (Exception e){
                    e.printStackTrace();
                }

            }

            @Override
            public void onFailure(Call<Product> call, Throwable t) {
                Log.e("response-failure", call.toString());
            }
        });
    }
}

我从布局onPostClicked()属性中调用了android:OnClicked方法。

我还编辑了AnroidManifest文件并添加了

<uses-permission android:name="android.permission.INTERNET" />

并且已连接到同一网络。

我使用POSTMAN尝试发送此邮件,并且它可以正常工作(将其添加到数据库中)

{
    "products": [
        {
            "product_name": "Galaxy A2",
            "product_price": 599.99
        }


    ]
}

当我发送GET请求时,它也显示它已添加新记录

{
    "products": [
        {
            "product_id": 1,
            "product_name": "Smart Watch",
            "product_price": 99.99
        },

        {
            "product_id": 2,
            "product_name": "Smart TV",
            "product_price": 999.99
        },
 {
                "product_id": 3,
                "product_name": "Galaxy A2",
                "product_price": 599.99
            }

    ]
}

这是我的日志

I/TAG: --> POST http://192.168.122.1/productmanager/products/ http/1.1
       Content-Type: application/json
       Content-Length: 249
       Accept: application/json
I/TAG: {"product_id":"","product_name":"Samsung Galaxy A5","product_price":234.5}
       --> END POST (249-byte body)
I/TAG: <-- 200 OK http://192.168.122.1/productmanager/products/addcproduct (266ms)
       Date: Fri, 28 Sep 2018 12:29:59 GMT
       Server: Apache/2.4.34 (Win32) OpenSSL/1.0.2o PHP/5.6.37
       X-Powered-By: PHP/5.6.37
       Keep-Alive: timeout=5, max=100
       Connection: Keep-Alive
       Transfer-Encoding: chunked
       Content-Type: text/html; charset=UTF-8
I/TAG: <pre class="cake-error"><a href="javascript:void(0);" onclick="document.getElementById('cakeErr5bae1ec79e019-trace').style.display = (document.getElementById('cakeErr5bae1ec79e019-trace').style.display == 'none' ? '' : 'none');"><b>Notice</b> (8)</a>: Undefined index: products [<b>APP/Controller\productsController.php</b>, line <b>77</b>]<div id="cakeErr5bae1ec79e019-trace" class="cake-stack-trace" style="display: none;"><a href="javascript:void(0);" onclick="document.getElementById('cakeErr5bae1ec79e019-code').style.display = (document.getElementById('cakeErr5bae1ec79e019-code').style.display == 'none' ? '' : 'none')">Code</a> <a href="javascript:void(0);" onclick="document.getElementById('cakeErr5bae1ec79e019-context').style.display = (document.getElementById('cakeErr5bae1ec79e019-context').style.display == 'none' ? '' : 'none')">Context</a><pre id="cakeErr5bae1ec79e019-code" class="cake-code-dump" style="display: none;"><code><span style="color: #000000"><span style="color: #0000BB">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$product&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$productTable</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">newEntity</span><span style="color: #007700">();</span></span></code>
       <span class="code-highlight"><code><span style="color: #000000"><span style="color: #0000BB">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$products&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">request</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">data</span><span style="color: #007700">[</span><span style="color: #DD0000">'products'</span><span style="color: #007700">];</span></span></code></span>
       <code><span style="color: #000000"><span style="color: #0000BB">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007700">if&nbsp;(</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">request</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">is</span><span style="color: #007700">(</span><span style="color: #DD0000">'post'</span><span style="color: #007700">))&nbsp;{</span></span></code></pre><pre id="cakeErr5bae1ec79e019-context" class="cake-context" style="display: none;">$res = []
       $productTable = object(App\Model\Table\ProductsTable) {

        &#039;registryAlias&#039; =&gt; &#039;products&#039;,
        &#039;table&#039; =&gt; &#039;products&#039;,
        &#039;alias&#039; =&gt; &#039;products&#039;,
        &#039;entityClass&#039; =&gt; &#039;App\Model\Entity\product&#039;,
        &#039;associations&#039; =&gt; [],
        &#039;behaviors&#039; =&gt; [],
        &#039;defaultConnection&#039; =&gt; &#039;default&#039;,
        &#039;connectionName&#039; =&gt; &#039;default&#039;

       }
       $product = object(App\Model\Entity\product) {

        &#039;[new]&#039; =&gt; true,
        &#039;[accessible]&#039; =&gt; [
            &#039;product_id&#039; =&gt; true,
            &#039;product_name&#039; =&gt; true,
            &#039;product_price&#039; =&gt; true,

        ],
        &#039;[dirty]&#039; =&gt; [],
        &#039;[original]&#039; =&gt; [],
        &#039;[virtual]&#039; =&gt; [],
        &#039;[errors]&#039; =&gt; [],
        &#039;[invalid]&#039; =&gt; [],
        &#039;[repository]&#039; =&gt; &#039;products&#039;

       }</pre><pre class="stack-trace">App\Controller\productsController::addproduct() - APP/Controller\ProductsController.php, line 77
       Cake\Controller\Controller::invokeAction() - CORE\src\Controller\Controller.php, line 440
       Cake\Http\ActionDispatcher::_invoke() - CORE\src\Http\ActionDispatcher.php, line 119
       Cake\Http\ActionDispatcher::dispatch() - CORE\src\Http\ActionDispatcher.php, line 93
       Cak
       <-- END HTTP (22852-byte body)
E/response-failure: retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall@4958691

请帮助。预先谢谢你

3 个答案:

答案 0 :(得分:1)

您需要将List的{​​{1}}作为Product传递。这意味着您的请求模型是一个包含@Body对象列表的对象

尝试创建像这样的POJO类

Product

注意:如果您将字段设为私有,则添加setter和getters

然后在您的改造界面中

        public class Product {
            @SerializedName("product_id")
            public int productId;
            @SerializedName("product_name")
            public String productName;
            @SerializedName("product_price")
            public double productPrice;
        }

        public class ProductRequest {
            @SerializedName("products")
            public List<Product> products;
        }

此外,不要将 Call<JsonObject> postRawJSON(@Body ProductRequest products); 用作响应JSON结构的POJO类

更新执行以下步骤

1)像这样创建JsonObject模型

ProductRequest

2)为此API的响应JSON创建POJO类。例如,创建一个 ProductRequest productRequest = new ProductRequest(); ArrayList<Product> productList = new ArrayList<>(); Product product = new Product(1, "Samsung Galaxy A5", 234.54); productList.add(product); productRequest.products = productList; 类。由于我不知道您的回复结构,因此我认为它类似于

ProductResponse

因此对于上面的Response,您必须创建如下的POJO类

{
  "code" : 200 , 
  "status" : "Success"
}

3)像这样创建您的 public class ProductResponse { @SerializedName("code") public int code; @SerializedName("status") public String status; } 界面

IRetrofit

4)现在,在您的 public interface IRetrofit { @Headers({ "Accept: application/json", "Content-Type: application/json" }) @POST("addproduct") Call<ProductResponse> addProducts(@Body ProductRequest productRequest); 中,下面是创建Activity(如步骤1所示)并调用API的完整代码

Request

答案 1 :(得分:0)

您的服务器要求您发送产品列表,在您的Android应用中,您要发送1个产品(1个Java模型)。您应该做的就是发送模型列表。

如果给班级取更好的名字,您本可以避免这个问题

Products products = new Products(null, "Samsung Galaxy A5", 234.54);

不好,因为您不是在创建产品 s ,而是在创建 a 产品。

答案 2 :(得分:0)

从您的JSON示例中可以看到,服务器接受 JSONObject ,其中包含产品 s

JSONArray

您使用具有与服务器可接受参数相同的Postman对其进行了测试。但是,在您的应用程序中,您正在准备Product类的对象,并将其传递给API请求。因此,最终的有效负载将如下所示,

{
    "product_id": 1,
    "product_name": "Smart Watch",
    "product_price": 99.99
}

只是产品的JSONObject而不是产品JSONArray。

按照@Srt在其answer中的建议进行操作。这是按照要求将数据发送到API的正确方法

我也看到了您在此处其他答案下发布的评论。在其中一个中,您说

  

没有错误,只是没有用。它不会添加新记录– S.Jay

要检查Retrofit执行网络请求时发生的情况,您需要添加OkHttpLoggingInterceptor,该日志记录通过Retrofit库执行的每个单个请求(包括错误)。

将此依赖项添加到您的build.gradle(应用级别)并同步项目

implementation 'com.squareup.okhttp3:logging-interceptor:3.8.0'

同步项目后,将以下代码添加到ServiceGenerator类中

import okhttp3.logging.HttpLoggingInterceptor;
import android.util.Log;

public class ServiceGenerator {

private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder();

public static <S> S createService(Class<S> serviceClass, String baseUrl) {

    // add logging interceptor to OkHttpClient
     httpClient.addInterceptor(getInterceptor());

    Retrofit builder = new Retrofit.Builder()
            .baseUrl(baseUrl)
            .addConverterFactory(GsonConverterFactory.create())
            .client(httpClient.build())
            .build();

      return builder.create(serviceClass);
    }

    public static HttpLoggingInterceptor getInterceptor() {
        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
           @Override
           public void log(String message) {
               Log.i("TAG", message);
           }
        });
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        return interceptor;
    }
}

就像我在上面的代码中提到的那样,只需将HttpLoggingInterceptor添加到OkHttpClient中即可。 (或复制并粘贴代码)

现在,这应该记录每个请求。