РАЗМЕЩЕНИЕ JSON-объекта массива JSON-объектов на сервере - PullRequest
0 голосов
/ 28 сентября 2018

Я пытаюсь отправить объект 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() из свойства layout 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>
$ res = []$ productTable = object (App \ Model \ Table \ ProductsTable) {'registryAlias' => 'products','table' => 'products','alias' => 'products','entityClass' => 'App \ Model \ Entity \ product','ассоциации' => [],'поведения' => [],'defaultConnection' => 'default','connectionName' => 'default'}$ product = object (App \ Model \ Entity \ product) {'[new]' => true,'[доступный]' => ['product_id' => true,'product_name' => true,'product_price' => true,],'[dirty]' => [],'[original]' => [],'[virtual]' => [],'[errors]' => [],'[invalid]' => [],'[repository]' => 'products'}
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
       

Пожалуйста, помогите.Заранее спасибо

Ответы [ 3 ]

0 голосов
/ 28 сентября 2018

Ваш сервер требует, чтобы вы отправили список продуктов, в вашем приложении для Android вы отправляете 1 продукт (1 модель Java).Что вам нужно сделать, это отправить список моделей.

Вы могли бы избежать этой проблемы, если бы дали своим классам лучшие имена

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

плохо, потому что вы не создаете продукт s но a product.

0 голосов
/ 28 сентября 2018

Как видно из вашего примера JSON, сервер принимает JSONObject , который содержит JSONArray продукта s

Вы протестировали его с помощью Postmanс теми же параметрами, которые принимает ваш сервер.Но в вашем приложении вы готовите объект класса Product и передаете его в запрос API.Итак, окончательная полезная нагрузка будет такой, как показано ниже:

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

Просто JSONObject продуктов вместо продуктов JSONArray.

Следуйте тому, что @ Srt предложено в его ответ .Это правильный способ отправки данных в ваш API (согласно требованию)

А также я натолкнулся на ваши комментарии, опубликованные под другими ответами здесь.В одном из них вы сказали:

Нет ошибки, она просто не работает. Она не добавляет новую запись - S.Jay

Чтобы проверить, что происходит, когда Retrofit выполняет сетевые запросы, вам нужно добавить OkHttpLoggingInterceptor , который регистрирует каждый отдельный запрос (включая ошибки), выполняемый через библиотеку Retrofit.

Добавить эту зависимость вваш build.gradle (уровень приложения) и синхронизируйте проект

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

После синхронизации проекта добавьте приведенный ниже код в ServiceGenerator class

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, как я упоминалв приведенном выше коде.(или скопируйте и вставьте код)

Теперь это должно регистрировать каждый отдельный запрос.

0 голосов
/ 28 сентября 2018

Вам необходимо передать List из Product как @Body.Это означает, что ваша модель запроса представляет собой объект, который содержит список Product объектов

Попробуйте создать классы POJO, подобные этому

        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);

Кроме того, вместо JsonObject используйте класс POJO для своей структуры JSON ответа

Обновление: Выполните следующие шаги

1) Создайте модель ProductRequest следующим образом

    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;

2) Создайте класс POJO дляответ JSON этого API.Например, создайте класс ProductResponse.Так как я не знаю вашу структуру ответа, я предполагаю, что это будет что-то вроде

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

Так что для приведенного выше ответа вам нужно создать класс POJO следующим образом:

 public class ProductResponse {
    @SerializedName("code")
    public int code;
    @SerializedName("status")
    public String status;
}

3) Создайте свой IRetrofit интерфейс следующим образом

    public interface IRetrofit {
    @Headers({
            "Accept: application/json",
            "Content-Type: application/json"
    })
    @POST("addproduct")
    Call<ProductResponse> addProducts(@Body ProductRequest productRequest);

4) Теперь в вашем Activity приведен полный код для создания Request (как показано на шаге 1) и вызовите API

    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;

    Call<ProductResponse> productResponseCall = jsonPostService.addProducts(productRequest);
    productResponseCall.enqueue(new Callback<ProductResponse>() {
        @Override
        public void onResponse(Call<ProductResponse> call, Response<ProductResponse> response) {
            ProductResponse productResponse = response.body(); // this  your result

        }

        @Override
        public void onFailure(Call<ProductResponse> call, Throwable t) {
            Log.e("response-failure", call.toString());
        }
    });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...