Working with Vertx JsonArray and RxJava Observables - rx-java2

A vertx JsonObject contains a vertx JsonArray, similar to:
{
"myArray":[
{"id":"1", name:"Yael" },
{"id":"2", name:"Haddasa"}
]
}
What is the correct way to create an RxJava Observable using the array, so that the observable will handle each element in the array separately. Have tried the following:
JsonArray vertxJsonArray = h.getJsonArray("myArray");
Observable<Object> observable = Observable.fromArray(vertxJsonArray);
observable.flatMapSingle(s -> {
...
But using the above, the array is not split up into separate elements.
Thanks

since JsonArray implements Iterable, you can use Observable.fromIterable(), like so:
#Test
public void from_iterable_test() {
final TestObserver<Object> testObserver = new TestObserver<>();
final String json = "{\"myArray\": [{\"id\": \"1\", \"name\": \"Yael\"}, {\"id\": \"2\", \"name\": \"Haddasa\"}] }";
final JsonObject jsonObject = new JsonObject(json);
final JsonArray jsonArray = jsonObject.getJsonArray("myArray");
Observable.fromIterable(jsonArray).subscribe(testObserver);
assertEquals(jsonArray.size(), testObserver.valueCount());
}

Related

how to POST Json object to a webservice

I am trying to consume a webservice and post the JSON object as request in my program. JSON is nested.
{
"paymentorder": {
"operation": "Purchase",
"currency": "NOK",
"amount": 15610,
"vatAmount": 3122,
"description": "Test Purchase",
"userAgent": "Mozilla/5.0...",
"language": "nb-NO",
"urls": {
"hostUrls": ["https://localhost:9002", "https://powertools.local:9002"],
"completeUrl": "https://powertools.local:9002/payment-completed",
"cancelUrl": "https://powertools.local:9002/payment-canceled",
"callbackUrl": "https://powertools.local:9002/payment-callback",
"termsOfServiceUrl": "https://powertools.local:9002/termsandconditoons.pdf"
},
"payeeInfo": {
"payeeId": "20f3341c-e570-40a1-b76f-5347f4866de8",
"payeeReference": "P4555334",
"payeeName": "Kiran Vemula",
"productCategory": "P00432101",
"orderReference" : "P45553234"
},
"payer": {
"consumerProfileRef": "63adb0760ebdcca15d8475773a59c3f3b03df6222dfcc9f5740ce1eb3465f58e"
}
}
}
the build the Hashmaps like below:
private Map<String, Object> initiatePaymentMenuRequestBody(){
final Map<String, Object> paymentorderChilds = new LinkedHashMap<String, Object>();
paymentorderChilds.put("operation", "Purchase");
paymentorderChilds.put("currency",currency);
paymentorderChilds.put("amount",amount);
paymentorderChilds.put("vatAmount",vatAmount);
paymentorderChilds.put("description",description);
paymentorderChilds.put("userAgent",userAgent);
paymentorderChilds.put("language",language);
paymentorderChilds.put("urls", initiatePaymentMenuURLs());
paymentorderChilds.put("payeeInfo", initiatePaymentMenuPayeeInfo());
paymentorderChilds.put("payer", initiatePaymentMenuPayer());
return paymentorderChilds;
}
private Map initiatePaymentMenuURLs(){
final Map<String, Object> initiatePaymentMenuURLs = new LinkedHashMap<String, Object>();
List<String> hostUrls = new ArrayList<>();
hostUrls.add(mediqHostUrls1);
hostUrls.add(mediqHostUrls2);
initiatePaymentMenuURLs.put("hostUrls",hostUrls);
initiatePaymentMenuURLs.put("completeUrl",completeUrl);
initiatePaymentMenuURLs.put("cancelUrl",cancelUrl);
initiatePaymentMenuURLs.put("callbackUrl",callbackUrl);
initiatePaymentMenuURLs.put("termsOfServiceUrl",termsOfServiceUrl);
return initiatePaymentMenuURLs;
}
// implement this method with the real data from B2CCustomer and Cart object
private Map initiatePaymentMenuPayeeInfo(){
Map<String, String> initiatePaymentMenuPayeeInfo = new LinkedHashMap<String, String>();
initiatePaymentMenuPayeeInfo.put("payeeId",metchantID);
initiatePaymentMenuPayeeInfo.put("payeeReference",payeeReference);
initiatePaymentMenuPayeeInfo.put("payeeName",payeeName);
initiatePaymentMenuPayeeInfo.put("productCategory",productCategory);
initiatePaymentMenuPayeeInfo.put("orderReference",orderReference);
return initiatePaymentMenuPayeeInfo;
}
private Map initiatePaymentMenuPayer(){
Map<String, String> initiatePaymentMenuPayer = new LinkedHashMap<String, String>();
initiatePaymentMenuPayer.put("consumerProfileRef", initiateConsumerSession());
return initiatePaymentMenuPayer;
}
and finally calling the webservice to post the data:
#Override
public String initiatePaymentMenu(PaymentOrder paymentOrder1) {
final RestTemplate restTemplate2 = new RestTemplate();
final UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(host+initiatePaymentMenuhostpostfix);
Map paymentOrder = new HashMap();
paymentOrder.put("paymentorder", initiatePaymentMenuRequestBody());
final HttpEntity entity = new HttpEntity(paymentOrder,getHeadders());
LOG.info("initiatePaymentMenu===========> "+entity.getBody());
ResponseEntity<String> payExInitiatePaymentMenuResponse = restTemplate2.postForEntity(builder.build().encode().toUri(),entity,String.class);
LOG.info("initiatePaymentMenu" +payExInitiatePaymentMenuResponse.getStatusCode());
String returnString = payExInitiatePaymentMenuResponse.getStatusCode().toString();
return returnString;
}
Is I am doing the correct way? I am not getting the response and giving me 400 error. Is entity.getBody() prints the exact JSON? can I use it in postman to check the response?
Thanks in advance.
Solved. The web service is not accepting 2 different URLs in hostUrls field. It was a bug in the web service provider itself.

Spring REST Endpoint Returning String instead of JSON

The following endpoint returns a username as a string.
How would I structure it to return a json object that contains a key with that string as its value (e.g., {"user":"joeuser"}?
#GetMapping(value = "/getUser", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<String> getUser() {
HttpHeaders responseHeaders = new HttpHeaders();
CustomUserAuthentication authentication = (CustomUserAuthentication) SecurityContextHolder.getContext().getAuthentication();
return ResponseEntity.ok().headers(responseHeaders).body(String.valueOf(authentication.getPrincipal()));
}
Using some Json library (like gson), build the Json object and return it in the body instead of the String. Make sure response content-type is application/json
You can also manually build the String that looks like Json but content to must be as above.
Spring can do what you want, but you need to return something that Spring needs to marshal into JSON. From my previous answer: https://stackoverflow.com/a/30563674/48229
#RequestMapping(value = "/json", method = RequestMethod.GET, produces = "application/json")
#ResponseBody
public Map<String, Object> bar() {
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("test", "jsonRestExample");
return map;
}

How to parse various answers from server and Retrofit

The server can answer like:
{ "data1":"value", "data2":"value" }
or:
{ "error":"text" }
or:
{ "json":"{ "error":"text" }" }
How to parse various answers from the server using retrofit.
Maybe I should make a rich POJO like:
class MyAnswer {
String data1;
String data2;
String error;
// etc
}
I recommend you to use Google's Gson library to Serialize/Deserialize Json strings to POJO's and deserialize back.
Retrofit2 also supports Gson as a converter.
Add compile 'com.squareup.retrofit2:converter-gson' to your build.gradle and create Retrofit instance like below:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build();
Define your Java classes and annotate them with Gson's SerializedName tag.
public class MyAnswer {
#SerializedName("data1")
public String data1;
#SerializedName("data2")
public String data2;
#SerializedName("error")
public String error;
}
Then you can get your POJO on the onResponse method:
#Override
public void onResponse(Call<ExampleClass> call, Response<ExampleClass> response) {
ExampleClass exampleClass = response.body();
......
}
You can also deserialize yourself from Json:
Gson gson = new GsonBuilder().create();
ExampleClass ec = gson.fromJson(jsonString, ExampleClass.class);
Or serialize to Json:
ExampleClass ec = new ExampleClass();
ec.data1 = "Some text";
ec.data2 = "Another text";
Gson gson = new GsonBuilder().create();
String jsonString = gson.toJson(ec);
You can also create nested/complex structures with Gson.
For more information, visit their user guide.

begin array but was string GSON

I have a Web Service REST :
#Path("/Vehicles")
public class Vehicles{
#GET
#Path("/Cars")
#Produces(aplicattion/json)
public String Cars() {
Car[] cars = Consulting my database...
Gson gson = new Gson();
return gson.toJson(cars);
}
I consume the web service:
try {
HttpClient httpClient = new DefaultHttpClient();
HttpGet get = new HttpGet(
"http://localhost:8080/Concessionaire/rest/Vehicles/Cars");
HttpResponse resp = httpClient.execute(get);
String respGET = EntityUtils.toString(resp.getEntity());
Gson gson = new Gson();
Cars[] c = gson.fromJson(respGET,Cars[].class);
}catch(Exception e){
}
But appears this exception: Expected BEGIN_ARRAY but was String at line 1 colum 6
What is the problem ?
Your method returns a String
public String Cars()
The client code expects a Car array
Cars[] c = gson.fromJson(respGET,Cars[].class);
Gson expects the BEGIN_ARRAY event while parsing the json but instead finds a String. To fix it, send a Cars[] using the jersey Response class and change the return type to Response.
return Response.ok(myCarsArray).build();

ASP.NET JSON Web Service Response format

I have written one simple web service which get product list in JSONText which is string object
Web Service code is below
using System;
using System.Collections.Generic;
using System.Web;
using System.Web.Services;
using System.Web.Script.Services;
using System.Runtime.Serialization.Json;
using System.IO;
using System.Text;
/// <summary>
/// Summary description for JsonWebService
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.Web.Script.Services.ScriptService]
public class JsonWebService : System.Web.Services.WebService
{
public JsonWebService () {
//Uncomment the following line if using designed components
//InitializeComponent();
}
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public string GetProductsJson(string prefix)
{
List<Product> products = new List<Product>();
if (prefix.Trim().Equals(string.Empty, StringComparison.OrdinalIgnoreCase))
{
products = ProductFacade.GetAllProducts();
}
else
{
products = ProductFacade.GetProducts(prefix);
}
//yourobject is your actula object (may be collection) you want to serialize to json
DataContractJsonSerializer serializer = new DataContractJsonSerializer(products.GetType());
//create a memory stream
MemoryStream ms = new MemoryStream();
//serialize the object to memory stream
serializer.WriteObject(ms, products);
//convert the serizlized object to string
string jsonString = Encoding.Default.GetString(ms.ToArray());
//close the memory stream
ms.Close();
return jsonString;
}
}
now it give me resoponse like below :
{"d":"[{\"ProductID\":1,\"ProductName\":\"Product 1\"},{\"ProductID\":2,\"ProductName\":\"Product 2\"},{\"ProductID\":3,\"ProductName\":\"Product 3\"},{\"ProductID\":4,\"ProductName\":\"Product 4\"},{\"ProductID\":5,\"ProductName\":\"Product 5\"},{\"ProductID\":6,\"ProductName\":\"Product 6\"},{\"ProductID\":7,\"ProductName\":\"Product 7\"},{\"ProductID\":8,\"ProductName\":\"Product 8\"},{\"ProductID\":9,\"ProductName\":\"Product 9\"},{\"ProductID\":10,\"ProductName\":\"Product 10\"}]"}
But i am looking for below out put
[{"ProductID":1,"ProductName":"Product 1"},{"ProductID":2,"ProductName":"Product 2"},{"ProductID":3,"ProductName":"Product 3"},{"ProductID":4,"ProductName":"Product 4"},{"ProductID":5,"ProductName":"Product 5"},{"ProductID":6,"ProductName":"Product 6"},{"ProductID":7,"ProductName":"Product 7"},{"ProductID":8,"ProductName":"Product 8"},{"ProductID":9,"ProductName":"Product 9"},{"ProductID":10,"ProductName":"Product 10"}]
can any one tell me what is actual problem
Thanks
First there was a change with ASP.NET 3.5 for security reasons Microsoft added the "d" to the response. Below is a link from Dave Ward at the Encosia that talks about what your seeing:
A breaking change between versions of ASP.NET AJAX. He has several posts that talks about this that can help you further with processing JSON and ASP.NET
Actually, if you just remove the
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
from the method, and you return the jsonString that you serialized using the JavaScriptSerializer you will get exactelly the output that you were looking for.
Notice that u have double quotes beside ur array in your response.In this way u return json format not json object from ur web method.Json format is a string.Therefore u have to use json.parse() function in order to parse json string to json object.If u dont want to use parse fuction,u have to remove serialize in ur web method.Thus u get a json object.
in .net web service
[WebMethod]
public string Android_DDD(string KullaniciKey, string Durum, string PersonelKey)
{
return EU.EncodeToBase64("{\"Status\":\"OK\",\"R\":[{\"ImzaTipi\":\"Paraf\", \"Personel\":\"Ali Veli üğişçöıÜĞİŞÇÖI\", \"ImzaDurumTipi\":\"Tamam\", \"TamamTar\":\"1.1.2003 11:21\"},{\"ImzaTipi\":\"İmza\", \"Personel\":\"Ali Ak\", \"ImzaDurumTipi\":\"Tamam\", \"TamamTar\":\"2.2.2003 11:21\"}]}");
}
static public string EncodeToBase64(string toEncode)
{
UTF8Encoding encoding = new UTF8Encoding();
byte[] bytes = encoding.GetBytes(toEncode);
string returnValue = System.Convert.ToBase64String(bytes);
return returnValue;
}
in android
private static String convertStreamToString(InputStream is)
{
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = null;
try
{
while ((line = reader.readLine()) != null)
{
sb.append(line + "\n");
}
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
try
{
is.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
return sb.toString();
}
private void LoadJsonDataFromASPNET()
{
try
{
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpPost httpPostRequest = new HttpPost(this.WSURL + "/WS.asmx/Android_DDD");
JSONObject jsonObjSend = new JSONObject();
jsonObjSend.put("KullaniciKey", "value_1");
jsonObjSend.put("Durum", "value_2");
jsonObjSend.put("PersonelKey", "value_3");
StringEntity se = new StringEntity(jsonObjSend.toString());
httpPostRequest.setEntity(se);
httpPostRequest.setHeader("Accept", "application/json");
httpPostRequest.setHeader("Content-type", "application/json");
// httpPostRequest.setHeader("Accept-Encoding", "gzip"); // only set this parameter if you would like to use gzip compression
HttpResponse response = (HttpResponse) httpclient.execute(httpPostRequest);
HttpEntity entity = response.getEntity();
if (entity != null)
{
InputStream instream = entity.getContent();
String resultString = convertStreamToString(instream);
instream.close();
resultString = resultString.substring(6, resultString.length()-3);
resultString = new String(android.util.Base64.decode(resultString, 0), "UTF-8");
JSONObject object = new JSONObject(resultString);
String oDurum = object.getString("Status");
if (oDurum.equals("OK"))
{
JSONArray jsonArray = new JSONArray(object.getString("R"));
if (jsonArray.length() > 0)
{
for (int i = 0; i < jsonArray.length(); i++)
{
JSONObject jsonObject = jsonArray.getJSONObject(i);
String ImzaTipi = jsonObject.getString("ImzaTipi");
String Personel = jsonObject.getString("Personel");
String ImzaDurumTipi = jsonObject.getString("ImzaDurumTipi");
String TamamTar = jsonObject.getString("TamamTar");
Toast.makeText(getApplicationContext(), "ImzaTipi:" + ImzaTipi + " Personel:" + Personel + " ImzaDurumTipi:" + ImzaDurumTipi + " TamamTar:" + TamamTar, Toast.LENGTH_LONG).show();
}
}
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
}