Below is the JSON, in which I need to parse the value of:
"primaryInvolvedParty":
{
}
The response is XML, hence it is converted into JSON, so that I can parse it easily.
Converting XML to JSON using:
String messageBody = actualResult.get("StatusMessage");
JSONObject xmlconvertedjson=XML.toJSONObject(messageBody);
JsonElement jelement = new
JsonParser().parse(xmlconvertedjson.toString());
But I am looking for the generic function where I can fetch the key-value for given attribute, for ex: customerScore.scoreResult= Accept,
Please help as I am new to Rest Assured parsing.
JSON:
{
"soap:Envelope": {
"soap:Header": "",
"xmlns:soap": "http://schemas.xmlsoap.org/soap/envelope/",
"soap:Body": {
"ns2:offerProductArrangementResponse": {
"xmlns:ns2": "http://LIB_SIM_SalesProcessManagement/IA_OfferProductArrangement",
"response": {
"productArrangement": {
"arrangementId": "317076",
"offeredProducts": {
"externalSystemProductIdentifier": [
{
"productIdentifier": "901",
"systemCode": "00107"
},
{
"productIdentifier": "201",
"systemCode": "10107"
},
{
"productIdentifier": "P_CLASSIC",
"systemCode": "00010"
},
{
"productIdentifier": "0071306000",
"systemCode": "00004"
},
{
"productIdentifier": "0071776000",
"systemCode": "00004"
}
],
"productIdentifier": "92",
"productoffer": {
"offerType": "2001"
},
"associatedFamily": {
"extsysprodfamilyidentifier": {
"productFamilyIdentifier": "502"
}
},
"productoptions": [
{
"optionsDescription": "Correspondence Default",
"optionsName": "Correspondence Default",
"optionsType": "CorrespDef",
"optionsValue": "Paper",
"optionsCode": "3521"
},
{
"optionsDescription": "Correspondence Option",
"optionsName": "Correspondence Option",
"optionsType": "CorrespOp",
"optionsValue": "Choice",
"optionsCode": "2944"
},
{
"optionsDescription": "Debit Card Funding",
"optionsName": "Debit Card Funding",
"optionsType": "DCF",
"optionsValue": "N",
"optionsCode": "3943"
},
{
"optionsDescription": "Product Priority",
"optionsName": "Product priority",
"optionsType": "PrdPriority",
"optionsValue": "5",
"optionsCode": "2658"
},
{
"optionsDescription": "Upsell Display Value",
"optionsName": "Upsell Display Value",
"optionsType": "UPSellDispval",
"optionsValue": "0",
"optionsCode": "2659"
},
{
"optionsDescription": "Account Switching",
"optionsName": "Account Switching",
"optionsType": "AccSwitching",
"optionsValue": "Y",
"optionsCode": "2662"
},
{
"optionsDescription": "VERDE PRODUCT ID",
"optionsName": "VERDE PRODUCT ID",
"optionsType": "VerdeProdId",
"optionsValue": "20051",
"optionsCode": "4523"
},
{
"optionsDescription": "Vantage Product Id for Verde",
"optionsName": "Vantage Product Id for Verde",
"optionsType": "VantProdIDVer",
"optionsValue": "20055",
"optionsCode": "4963"
},
{
"optionsDescription": "isVantage",
"optionsName": "isVantage",
"optionsType": "isVantage",
"optionsValue": "No",
"optionsCode": "6659"
},
{
"optionsDescription": "Overdraft Offer Flag",
"optionsName": "Overdraft Offer Flag",
"optionsType": "OD_Offer_Flag",
"optionsValue": "Y",
"optionsCode": "6905"
},
{
"optionsDescription": "Make_It_Joint",
"optionsName": "Make_It_Joint",
"optionsType": "MkItJoint",
"optionsValue": "1",
"optionsCode": "6975"
},
{
"optionsDescription": "Survey",
"optionsName": "Survey",
"optionsType": "Survey",
"optionsValue": "Y",
"optionsCode": "7288"
},
{
"optionsDescription": "Statement Option",
"optionsName": "Statement Option",
"optionsType": "StateOp",
"optionsValue": "Choice",
"optionsCode": "1099"
},
{
"optionsDescription": "Statement Default",
"optionsName": "Statement Default",
"optionsType": "StateDef",
"optionsValue": "Paper",
"optionsCode": "1770"
},
{
"optionsDescription": "Tariff",
"optionsName": "Tariff",
"optionsType": "TRF",
"optionsValue": "1",
"optionsCode": "2663"
}
],
"productName": "Classic Account"
},
"applicationType": "10001",
"xsi:type": "ns7:DepositArrangement",
"isOverdraftRequired": "true",
"xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance",
"xmlns:ns7": "http://LIB_SIM_BO/BusinessObjects",
"primaryInvolvedParty": {
"auditData": [
{
"auditTime": "132551",
"auditType": "PARTY_EVIDENCE",
"auditDate": "12012018"
},
{
"auditTime": "132551",
"auditType": "ADDRESS_EVIDENCE",
"auditDate": "12012018"
},
{
"auditTime": "132551",
"auditType": "ADDRESS",
"auditDate": "12012018"
}
],
"isAuthCustomer": "false",
"cidPersID": "+00554133625",
"customerSegment": "3",
"individualIdentifier": "249894",
"newCustomerIndicator": "true",
"customerIdentifier": "2012794088",
"customerScore": [
{
"scoreResult": "ACCEPT",
"assessmentType": "EIDV",
"decisionText": "001",
"decisionCode": "I",
"assessmentEvidence": {
"addressStrength": "900",
"evidenceIdentifier": "4696198HL890678339009003211586646102",
"identityStrength": "900"
}
},
{
"scoreResult": "1",
"assessmentType": "ASM",
"referralCode": [
{
"code": "601",
"description": "Accept."
},
{
"code": "601",
"description": "Accept."
}
],
"scoreIdentifier": "647448142"
}
]
},
"arrangementType": "CA",
"applicationStatus": "1002",
"associatedProduct": {},
"conditions": [
{
"result": "No",
"name": "INTEND_TO_SWITCH"
},
{
"result": "true",
"name": "INTEND_TO_OVERDRAFT"
},
{
"result": "Y",
"name": "CHECK_BOOK_OFFERED_FLAG"
},
{
"result": "20",
"name": "DEBIT_CARD_RISK_CODE"
},
{
"result": "4",
"name": "OVERDRAFT_RISK_CODE"
}
],
"overdraftDetails": {
"amount": {
"amount": "3001"
}
}
},
"header": {
"interactionId": "ucoGI58OmuY0bfYXx2iLqta",
"LloydsHeaders": [
{
"prefix": "ns4",
"name": "ServiceRequest",
"nameSpace": "http://www.lloydstsb.com/Schema/Infrastructure/SOAP",
"value": {
"ns5:From": "10.245.211.214",
"xsi:type": "ns5:ServiceRequest",
"ns5:Action": "offerProductArrangement",
"ns5:ServiceName": "offerProductArrangement",
"xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance",
"ns5:mustReturn": "false",
"ns5:MessageId": "ucoGI58OmuY0bfYXx2iLqta"
}
},
{
"prefix": "ns4",
"name": "ContactPoint",
"nameSpace": "http://www.lloydstsb.com/Schema/Infrastructure/SOAP",
"value": {
"ns5:OperatorType": "Customer",
"ns5:ContactPointId": "0000777505",
"ns5:ApplicationId": "AL07618",
"ns5:InitialOriginatorId": "10.245.224.125",
"xsi:type": "ns5:ContactPoint",
"xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance",
"ns5:mustReturn": "false",
"ns5:InitialOriginatorType": "Browser",
"ns5:ContactPointType": "003"
}
},
{
"prefix": "ns5",
"name": "bapiInformation",
"nameSpace": "http://www.lloydstsb.com/Schema/Enterprise/LCSM",
"value": {
"ns4:BAPIId": "B001",
"xsi:type": "ns4:bapiInformation",
"ns4:BAPIOperationalVariables": {
"ns4:bForceHostCall": "false",
"ns4:bBatchRetry": "false",
"ns4:bPopulateCache": "false"
},
"xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance",
"ns4:BAPIHeader": {
"ns4:acceptLanguage": {
"xsi:nil": "true"
},
"ns4:inboxidClient": "GX",
"ns4:cctmauthcd": {
"xsi:nil": "true"
},
"ns4:encVerNo": {
"xsi:nil": "true"
},
"ns4:sessionid": "ucoGI58OmuY0bfYXx2iLqta",
"ns4:useridAuthor": "UNAUTHSALE",
"ns4:userAgent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36",
"ns4:chanidObo": {
"xsi:nil": "true"
},
"ns4:stpartyObo": {
"ns4:ocisid": "737704834",
"ns4:partyid": "+00263174828",
"ns4:host": "I"
},
"ns4:chanid": "IBL",
"ns4:ipAddressCaller": {
"xsi:nil": "true"
},
"ns4:chanctxt": "1",
"ns4:callerlineid": {
"xsi:nil": "true"
},
"ns4:chansecmode": "PWD"
}
}
},
{
"prefix": "lgsm",
"name": "Security",
"nameSpace": "http://LB_GBO_Sales/Messages",
"value": {
"mustReturn": "false",
"ns3:UsernameToken": {
"ns3:Username": "UNAUTHSALE",
"ns3:UNPMechanismType": "NTLM",
"Id": "LloydsTSBSecurityToken",
"ns3:UserType": "013"
},
"xsi:type": "ns3:SecurityHeaderType",
"xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance"
}
}
],
"businessTransaction": "OfferProductArrangement",
"channelId": "LTB"
}
},
"xmlns:ns5": "http://www.lloydstsb.com/Schema/Infrastructure/SOAP",
"xmlns:ns3": "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd",
"xmlns:ns4": "http://www.lloydstsb.com/Schema/Enterprise/LCSM"
}
}
}
}
I think you can build your function using XPath or JsonPath as base of your solution
The specified json response is nested. Through method chaining technique the code can be written as follows:
String messageBody = actualResult.get("StatusMessage");
JSONObject xmlconvertedjson=XML.toJSONObject(messageBody);
JsonElement primaryInvolvedParty = xmlconvertedjson.get("soap:Envelope").getAsJsonObject().get("soap:Body").getAsJsonObject().get("ns2:offerProductArrangementResponse").getAsJsonObject().get("response").getAsJsonObject().get("productArrangement").getAsJsonObject().get("primaryInvolvedParty");
For readability this code can be written as follows:
String messageBody = actualResult.get("StatusMessage");
JSONObject xmlconvertedjson = XML.toJSONObject(messageBody);
JsonElement soapEnvelope = xmlconvertedjson.getAsJsonObject().get("soap:Envelope");
JsonElement soapBody = soapEnvelope.getAsJsonObject().get("soap:Body");
JsonElement ns2offerProductArrangementResponse = soapBody.getAsJsonObject().get("ns2:offerProductArrangementResponse");
JsonElement response = ns2offerProductArrangementResponse.getAsJsonObject().get("response");
JsonElement productArrangement = response.getAsJsonObject().get("productArrangement");
JsonElement primaryInvolvedParty = productArrangement.getAsJsonObject().get("primaryInvolvedParty");
#Nithin Dhanyavadagalu
Thanks for the solution.Below code worked , but looking for some generic code.
String messageBody = actualResult.get("StatusMessage");
JSONObject xmlconvertedjson=XML.toJSONObject(messageBody);
JsonElement jelement = new JsonParser().parse(xmlconvertedjson.toString());
JsonObject jobject = jelement.getAsJsonObject();
System.out.println("Parsed json object"+jobject);
JsonElement soapEnvelope = jobject.get("soap:Envelope").getAsJsonObject().get("soap:Body").getAsJsonObject().get("ns2:offerProductArrangementResponse").getAsJsonObject().get("response").getAsJsonObject().get("productArrangement");
JsonElement primaryInvolvedParty = soapEnvelope.getAsJsonObject().get("primaryInvolvedParty");
JsonElement audit = primaryInvolvedParty.getAsJsonObject().get("customerScore");
System.out.println("Primaryparty:"+audit);
JsonArray jsonarray = audit.getAsJsonArray();
System.out.println( jsonarray.get(0).getAsJsonObject().get("scoreResult"));
System.out.println( jsonarray.get(0).getAsJsonObject().get("assessmentType"));
System.out.println( jsonarray.get(1).getAsJsonObject().get("assessmentType"));
Related
I have some JSON, declared as string for my testing purposes in main method.
My goal is to use JSONPATH with DocumentContext, to override property if property exists, and to add it if it does not exists.
Is there possibility to achieve that ?
My JSON
How to add new node to Json using JsonPath?
Convert a JSON object to another JSON object in Java
I've visited these two but my result is not JSON but "com.jayway.jsonpath.internal.JsonReader#1ae369b7"
{
"meta": {
"drilldownEnabled": false
},
"chart": {
renderTo:"container",
"additionalData": {
"dateTime": false,
"datetype": "string",
"cliccable": true,
"drillable": false,
"drillableChart": false,
"isCockpit": true,
"categoryColumn": "periodo_analisi",
"categoryGroupBy": "",
"categoryGroupByNamens": "",
"categoryName": "periodo_analisi",
"categoryOrderColumn": "",
"categoryOrderType": "",
"categoryStacked": "",
"categoryStackedType": ""
},
"zoomType": "xy",
"panning": true,
"type": "column",
"options3d": {
"enabled": false,
"alpha": 25,
"beta": 15,
"depth": 50,
"viewDistance": 25
},
"backgroundColor": "#FFFFFF",
"heightDimType": "pixels",
"widthDimType": "pixels",
"plotBackgroundColor": null,
"plotBorderWidth": null,
"plotShadow": false,
"borderColor": "#FFFFFF",
"style": {
"backgroundColor": "#FFFFFF",
"fontFamily": "",
"fontWeight": "",
"fontSize": ""
},
"events": {}
},
"colors": [
"#ff5722"
],
"title": {
"text": "",
"style": {
"align": "",
"color": "",
"fontFamily": "",
"fontSize": "",
"fontWeight": ""
}
},
"legend": {
"enabled": false
},
"xAxis": [
{
"plotBands": [
{
"label": {
"text": "",
"align": "center"
},
"color": "",
"from": 0,
"to": 0
}
],
"plotLines": [
{
"label": {
"text": "",
"align": "center"
},
"color": "",
"dashStyle": "",
"value": 0,
"width": 0
}
],
"type": "category",
"id": 0,
"title": {
"customTitle": false,
"text": "periodo_analisi",
"style": {}
},
"labels": {
"style": {
"color": "",
"fontFamily": "",
"fontSize": "",
"fontWeight": ""
},
"align": ""
}
}
],
"yAxis": [
{
"plotBands": [
{
"label": {
"text": "",
"align": "center"
},
"color": "",
"from": 0,
"to": 0
}
],
"plotLines": [
{
"label": {
"text": "",
"align": "center"
},
"color": "",
"dashStyle": "",
"value": 0,
"width": 0,
"zIndex": 1
}
],
"title": {
"text": "NUM_GG_GIACENZA_AVG",
"customTitle": false,
"style": {
"color": "",
"fontFamily": "",
"fontWeight": "",
"fontSize": ""
}
},
"labels": {
"style": {
"color": "",
"fontFamily": "",
"fontSize": "",
"fontWeight": ""
},
"align": ""
},
"gridLineDashStyle": "$convertedTypeline",
"minorGridLineDashStyle": "$convertedMinorTpeline"
}
],
"series": [
{
"name": "NUM_GG_GIACENZA_AVG",
"dataLabels": {
"style": {
"color": "",
"fontFamily": "",
"fontWeight": "",
"fontSize": "",
"fontStyle": ""
},
"enabled": true,
"labelFormat": "{y:,.2f}"
},
"data": [
{
"drilldown": false,
"y": 32.6667,
"name": "Q1-2019",
"datetype": "string"
},
{
"drilldown": false,
"y": 29,
"name": "Q3-2018",
"datetype": "string"
},
{
"drilldown": false,
"y": 134.5,
"name": "Q4-2018",
"datetype": "string",
"color": "#F10AE8"
}
],
"selected": true,
"tooltip": {
"valueDecimals": 2,
"scaleFactor": "empty",
"ttBackColor": "#FCFFC5"
},
"yAxis": 0
}
],
"tooltip": {
"borderWidth": 0,
"borderRadius": 0,
"followTouchMove": false,
"followPointer": true,
"useHTML": true,
"backgroundColor": null,
"style": {
"padding": 0
}
},
"lang": {
"noData": ""
},
"noData": {
"style": {
"fontFamily": "",
"fontSize": "",
"color": ""
},
"position": {
"align": "center",
"verticalAlign": "middle"
}
},
"credits": {
"enabled": false
},
"plotOptions": {
"line": {
"marker": {
"symbol": "circle",
"lineWidth": 2
}
},
"column": {},
"bar": {},
"series": {
"cursor": "pointer",
"point": {
"events": {}
},
"dataLabels": {
"allowOverlap": true
},
"turboThreshold": 2000
}
}
}
I simply place this JSON in string as cc variable and write
DocumentContext doc = JsonPath.parse(cc).set(JsonPath.compile("$.meta"), "nani");
doc.json();
System.out.println(doc);
You're printing the DocumentContext instance instead of its content.
Try:
System.out.println(doc.read([Your JsonPath]));
Go here for more Info.
I am trying to validate a json payload against a swagger file that contains the service agreement. I am using the json-schema-validator(2.1.7) library to achieve this, but at the moment it's not validating against the specified patterns or min/max length.
Java Code:
public void validateJsonData(final String jsonData) throws IOException, ProcessingException {
ClassLoader classLoader = getClass().getClassLoader();
File jsonSchemaFile = new File (classLoader.getResource("coachingStatusUpdate.json").getFile());
String jsonSchema = new String(Files.readAllBytes(jsonSchemaFile.toPath()));
final JsonNode dataNode = JsonLoader.fromString(jsonData);
final JsonNode schemaNode = JsonLoader.fromString(jsonSchema);
final JsonSchemaFactory factory = JsonSchemaFactory.byDefault();
JsonValidator jsonValidator = factory.getValidator();
ProcessingReport report = jsonValidator.validate(schemaNode, dataNode);
System.out.println(report);
if (!report.toString().contains("success")) {
throw new ProcessingException (
report.toString());
}
}
Message I am sending through
{
"a": "b",
"c": "d",
"e": -1,
"f": "2018-10-30",
"g": "string" }
The swagger definition:
{
"swagger": "2.0",
"info": {
"version": "1.0.0",
"title": "Test",
"termsOfService": "http://www.test.co.za",
"license": {
"name": "Test"
}
},
"host": "localhost:9001",
"basePath": "/test/",
"tags": [
{
"name": "controller",
"description": "Submission"
}
],
"paths": {
"/a": {
"put": {
"tags": [
"controller"
],
"summary": "a",
"operationId": "aPUT",
"consumes": [
"application/json;charset=UTF-8"
],
"produces": [
"application/json;charset=UTF-8"
],
"parameters": [
{
"in": "body",
"name": "aRequest",
"description": "aRequest",
"required": true,
"schema": {
"$ref": "#/definitions/aRequest"
}
}
],
"responses": {
"200": {
"description": "Received",
"schema": {
"$ref": "#/definitions/a"
}
},
"400": {
"description": "Bad Request"
},
"401": {
"description": "Unauthorized"
},
"408": {
"description": "Request Timeout"
},
"500": {
"description": "Generic Error"
},
"502": {
"description": "Bad Gateway"
},
"503": {
"description": "Service Unavailable"
}
}
}
}
},
"definitions": {
"aRequest": {
"type": "object",
"required": [
"a",
"b",
"c",
"d"
],
"properties": {
"a": {
"type": "string",
"description": "Status",
"enum": [
"a",
"b",
"c",
"d",
"e",
"f",
"g",
"h"
]
},
"aReason": {
"type": "string",
"description": "Reason",
"enum": [
"a",
"b",
"c",
"d",
"e",
"f",
"g",
"h",
"i",
"j",
"k",
"l",
"m",
"n"
]
},
"correlationID": {
"type": "integer",
"format": "int32",
"description": "",
"minimum": 1,
"maximum": 9999999
},
"effectiveDate": {
"type": "string",
"format": "date",
"description": ""
},
"f": {
"type": "string",
"description": "",
"minLength": 1,
"maxLength": 100
}
}
},
"ResponseEntity": {
"type": "object",
"properties": {
"body": {
"type": "object"
},
"statusCode": {
"type": "string",
"enum": [
"100",
"101",
"102",
"103",
"200",
"201",
"202",
"203",
"204",
"205",
"206",
"207",
"208",
"226",
"300",
"301",
"302",
"303",
"304",
"305",
"307",
"308",
"400",
"401",
"402",
"403",
"404",
"405",
"406",
"407",
"408",
"409",
"410",
"411",
"412",
"413",
"414",
"415",
"416",
"417",
"418",
"419",
"420",
"421",
"422",
"423",
"424",
"426",
"428",
"429",
"431",
"451",
"500",
"501",
"502",
"503",
"504",
"505",
"506",
"507",
"508",
"509",
"510",
"511"
]
},
"statusCodeValue": {
"type": "integer",
"format": "int32"
}
}
}
}
}
As you can see I am sending through a correlationID of -1, which should fail validation, but at the moment is's returning as successful:
com.github.fge.jsonschema.report.ListProcessingReport: success
I suggest using this library, which worked for me:
https://github.com/bjansen/swagger-schema-validator
Example:
invalid-pet.json
{
"id": 0,
"category": {
"id": 0,
"name": "string"
},
"named": "doggie",
"photoUrls": [
"string"
],
"tags": [
{
"id": 0,
"name": "string"
}
],
"status": "available"
}
My SchemaParser:
#Component
public class SchemaParser {
private Logger logger = LoggerFactory.getLogger(getClass());
public boolean isValid(String message, Resource schemaLocation) {
try (InputStream inputStream = schemaLocation.getInputStream()) {
SwaggerValidator validator = SwaggerValidator.forJsonSchema(new InputStreamReader(inputStream));
ProcessingReport report = validator.validate(message, "/definitions/Pet");
return report.isSuccess();
} catch (IOException e) {
logger.error("IOException", e);
return false;
} catch (ProcessingException e) {
e.printStackTrace();
return false;
}
}
}
A test:
#Test
void shouldFailValidateWithPetstoreSchema() throws IOException {
final Resource validPetJson = drl.getResource("http://petstore.swagger.io/v2/swagger.json");
try (Reader reader = new InputStreamReader(validPetJson.getInputStream(), UTF_8)) {
final String petJson = FileCopyUtils.copyToString(reader);
final boolean valid = schemaParser.isValid(petJson, petstoreSchemaResource);
assertFalse(valid);
}
}
json-schema-validator seems to work with pure JSON Schema only. OpenAPI Specification uses an extended subset of JSON Schema, so the schema format is different. You need a library that can validate specifically against OpenAPI/Swagger definitions, such as Atlassian's swagger-request-validator.
response:
[
{
"id": "e9299032e8a34d168def176af7d62da3",
"createdAt": "Nov 8, 2017 9:46:40 AM",
"model": {
"id": "eeed0b6733a644cea07cf4c60f87ebb7",
"name": "color",
"app_id": "main",
"created_at": "May 11, 2016 11:35:45 PM",
"model_version": {}
},
"input": {
"id": "df6eae07cd86483f811c5a2202e782eb",
"data": {
"concepts": [],
"metadata": {},
"image": {
"url": "http://www.sachinmittal.com/wp-content/uploads/2017/04/47559184-image.jpg"
}
}
},
"data": [
{
"hex": "#f59b2d",
"webSafeHex": "#ffa500",
"webSafeColorName": "Orange",
"value": 0.0605
},
{
"hex": "#3f1303",
"webSafeHex": "#000000",
"webSafeColorName": "Black",
"value": 0.2085
},
{
"hex": "#a33303",
"webSafeHex": "#8b0000",
"webSafeColorName": "DarkRed",
"value": 0.3815
},
{
"hex": "#000000",
"webSafeHex": "#000000",
"webSafeColorName": "Black",
"value": 0.34275
},
{
"hex": "#f7ce93",
"webSafeHex": "#ffdead",
"webSafeColorName": "NavajoWhite",
"value": 0.00675
}
],
"status": {}
}
]
need to parse this reponse in json. Please help me out.
You can try something like this..
try{
JSONArray array= new JSONArray(Yourresponse);
for(int i=0; i<=array.length();i++){
JSONObject jsonObject=array.getJSONObject(i);
String id= jsonObject.getString("id");
String created_at= jsonObject.getString("createdAt");
String model_id = jsonObject.getJSONObject("model").getString("id");
String app_id=jsonObject.getJSONObject("model").getString("app_id");
//So On... Depends on your requirements. It's just an idea!
}
}
catch (Exception e){
e.printStackTrace();
}
I am using retrofit2 to Make network request,I have searched over here but my bad luck i couldn't find any working solution. that's why i am putting my question here.
my JSON response is given below.
The problem is sometimes the REST API returns an Array of hour , but sometimes it is just a Object. How does one handle such a situation?
Is there an elegant way to handle a mixed array like this in Retrofit/Gson? I'm not responsible for the data coming from the API, so I don't think changing that will be an option.Any help would be appreciated.
{
"status": "success",
"data": [
{
"id": 30,
"name": "Rh.poutiqe",
"global_delay": "0",
"approved": true,
"min_order": "0.000",
"has_pickup": 0,
"address": {
"id": "35",
"name": "Store Address",
"type": "house",
"block_number": "8",
"street": "85",
"avenue": "0",
"building": "2",
"floor": "",
"apartment": "",
"directions": "",
"lat": null,
"lng": null,
"city": {
"id": "79",
"name": "Bayan",
"zone": "3",
"governate": "Hawally"
}
},
"status": "Available",
"owner": {
"id": "32",
"username": "+96550199900",
"creation_date": "2017-08-07 09:46:49",
"info": {
"name": "Asmaa alkandri",
"email": "Asooma_q8#hotmail.com",
"mobile": "50199900",
"store_id": "30",
"device_token": "e01efb2f03cd43509242c7b38ca890471db2e5b056f50b7a3661c34ab45b0b6e"
},
"addresses": [
{
"id": "35",
"name": "Store Address",
"type": "house",
"block_number": "8",
"street": "85",
"avenue": "0",
"building": "2",
"floor": "",
"apartment": "",
"directions": "",
"lat": null,
"lng": null,
"city": {
"id": "79",
"name": "Bayan",
"zone": "3",
"governate": "Hawally"
}
}
]
},
"open": false,
"image": {
"src": "https://api.bits.com.kw/assets/stores/30/y1nzl.jpg"
},
"hours": {
"2": [
{
"id": "117",
"day_id": "2",
"day_of_week": "Tuesday",
"start_hour": "1400",
"end_hour": "2300"
}
],
"3": [
{
"id": "118",
"day_id": "3",
"day_of_week": "Wednesday",
"start_hour": "1400",
"end_hour": "2300"
}
]
},
"next_available": {
"day_of_week": "Tuesday",
"start_hour": "1400",
"end_hour": "2300",
"day_id": "2",
"date": "2017-09-19"
}
},
{
"id": 57,
"name": "RH Kitchen",
"global_delay": "0",
"approved": true,
"min_order": "0.000",
"has_pickup": 0,
"address": {
"id": "63",
"name": "Store Address",
"type": "house",
"block_number": "5",
"street": "2",
"avenue": "",
"building": "97",
"floor": "",
"apartment": "",
"directions": "",
"lat": null,
"lng": null,
"city": {
"id": "79",
"name": "Bayan",
"zone": "3",
"governate": "Hawally"
}
},
"status": "Not Receiving Orders",
"owner": {
"id": "57",
"username": "+96566659454",
"creation_date": "2017-09-09 11:32:19",
"info": {
"name": "RH Kitchen",
"email": "taiba.aldarmi#gmail.com",
"mobile": "66659454",
"store_id": "57",
"device_token": "f6fffd3a393e9aea53863cffbb55b51a3afd2475e952091ea362a85fc930ec9a"
},
"addresses": [
{
"id": "63",
"name": "Store Address",
"type": "house",
"block_number": "5",
"street": "2",
"avenue": "",
"building": "97",
"floor": "",
"apartment": "",
"directions": "",
"lat": null,
"lng": null,
"city": {
"id": "79",
"name": "Bayan",
"zone": "3",
"governate": "Hawally"
}
}
]
},
"open": false,
"image": {
"src": "https://api.bits.com.kw/placeholder.jpg"
},
"hours": [],
"next_available": false
},
{
"id": 64,
"name": "Lets__shop",
"global_delay": "1440",
"approved": true,
"min_order": "5.000",
"has_pickup": 0,
"address": {
"id": "64",
"name": "Store Address",
"type": "house",
"block_number": "3",
"street": "312",
"avenue": "",
"building": "56",
"floor": "",
"apartment": "",
"directions": "",
"lat": "0.000000000000000000",
"lng": "0.000000000000000000",
"city": {
"id": "126",
"name": "Saad Al Abdullah",
"zone": "9",
"governate": "Jahra"
}
},
"status": "Available",
"owner": {
"id": "58",
"username": "+96555899184",
"creation_date": "2017-09-09 18:33:12",
"info": {
"name": "Moneera ibrahim",
"email": "Moneeera96#gmail.com",
"mobile": "55899184",
"store_id": "64",
"device_token": null
},
"addresses": [
{
"id": "64",
"name": "Store Address",
"type": "house",
"block_number": "3",
"street": "312",
"avenue": "",
"building": "56",
"floor": "",
"apartment": "",
"directions": "",
"lat": "0.000000000000000000",
"lng": "0.000000000000000000",
"city": {
"id": "126",
"name": "Saad Al Abdullah",
"zone": "9",
"governate": "Jahra"
}
}
]
},
"open": true,
"next_available": {
"day_of_week": "Today",
"start_hour": "1646",
"end_hour": "2230",
"day_id": "0",
"date": "2017-09-17 1646"
},
"image": {
"src": "https://api.bits.com.kw/assets/stores/64/0xqh4.jpg"
},
"hours": [
[
{
"id": "161",
"day_id": "0",
"day_of_week": "Sunday",
"start_hour": "730",
"end_hour": "2230"
}
],
[
{
"id": "162",
"day_id": "1",
"day_of_week": "Monday",
"start_hour": "730",
"end_hour": "2230"
}
],
[
{
"id": "163",
"day_id": "2",
"day_of_week": "Tuesday",
"start_hour": "730",
"end_hour": "2230"
}
],
[
{
"id": "164",
"day_id": "3",
"day_of_week": "Wednesday",
"start_hour": "730",
"end_hour": "2230"
}
],
[
{
"id": "165",
"day_id": "4",
"day_of_week": "Thursday",
"start_hour": "730",
"end_hour": "2230"
}
],
[
{
"id": "166",
"day_id": "5",
"day_of_week": "Friday",
"start_hour": "730",
"end_hour": "2230"
}
],
[
{
"id": "167",
"day_id": "6",
"day_of_week": "Saturday",
"start_hour": "730",
"end_hour": "2230"
}
]
]
}
]
}
I have Make POJO class like:
public class StoreModel implements Parcelable{
#SerializedName("id")
public int id;
#SerializedName("name")
public String name;
#SerializedName("global_delay")
public String global_delay;
#SerializedName("approved")
public boolean approved;
#SerializedName("min_order")
public String min_order;
#SerializedName("has_pickup")
public int has_pickup;
#SerializedName("address")
public AddressModel address;
#SerializedName("status")
public String status;
#SerializedName("owner")
public OwnerModel owner;
#SerializedName("open")
public boolean open;
#SerializedName("next_available")
public Object next_available;
#SerializedName("image")
public ImageModel image;
protected StoreModel(Parcel in) {
id = in.readInt();
name = in.readString();
global_delay = in.readString();
approved = in.readByte() != 0;
min_order = in.readString();
has_pickup = in.readInt();
address = in.readParcelable(AddressModel.class.getClassLoader());
status = in.readString();
owner = in.readParcelable(OwnerModel.class.getClassLoader());
open = in.readByte() != 0;
image = in.readParcelable(ImageModel.class.getClassLoader());
//next_available = in.readParcelable(NextAvailableModel.class.getClassLoader());
}
public static final Creator<StoreModel> CREATOR = new Creator<StoreModel>() {
#Override
public StoreModel createFromParcel(Parcel in) {
return new StoreModel(in);
}
#Override
public StoreModel[] newArray(int size) {
return new StoreModel[size];
}
};
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeInt(id);
parcel.writeString(name);
parcel.writeString(global_delay);
parcel.writeByte((byte) (approved ? 1 : 0));
parcel.writeString(min_order);
parcel.writeInt(has_pickup);
parcel.writeParcelable(address, i);
parcel.writeString(status);
parcel.writeParcelable(owner, i);
parcel.writeByte((byte) (open ? 1 : 0));
parcel.writeParcelable(image, i);
/*if(next_available instanceof NextAvailableModel)
parcel.writeParcelable((NextAvailableModel)next_available, i);
else if(next_available instanceof Boolean)
parcel.writeByte((byte) ((Boolean)next_available ? 1 : 0));*/
}
#SerializedName("hours")
#Expose
public List<List<HoursModel>> hours;
}
**And HoursModel Java Class**
public class HoursModel implements Parcelable{
#SerializedName("id")
public String id;
#SerializedName("day_id")
public String day_id;
#SerializedName("day_of_week")
public String day_of_week;
#SerializedName("start_hour")
public String start_hour;
#SerializedName("end_hour")
public String end_hour;
protected HoursModel(Parcel in) {
id = in.readString();
day_id = in.readString();
day_of_week = in.readString();
start_hour = in.readString();
end_hour = in.readString();
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(id);
dest.writeString(day_id);
dest.writeString(day_of_week);
dest.writeString(start_hour);
dest.writeString(end_hour);
}
#Override
public int describeContents() {
return 0;
}
public static final Creator<HoursModel> CREATOR = new Creator<HoursModel>() {
#Override
public HoursModel createFromParcel(Parcel in) {
return new HoursModel(in);
}
#Override
public HoursModel[] newArray(int size) {
return new HoursModel[size];
}
};
}
First, if possible, verify if you can fix this braindead API. :)
First of all, notice that the API returns 2 very different types of data:
list of hours (no keys)
map of hours (each element has a key!)
You'll need to represent this structure in your POJO somehow. Maybe a list of key-hour pairs, like List<Pair<String, Hour>, with nullable key? Your call.
Second, you need to create a custom TypeAdapter that can deserialize a list and/or map into a Java object.
Once you have a type adapter, you can either attach it to a field using #JsonAdapter annotation, or register custom type in Gson builder.
https://google.github.io/gson/apidocs/com/google/gson/annotations/JsonAdapter.html
http://www.javacreed.com/gson-typeadapter-example/
I searched across many sources but could not find the answer to this one..
Its a know fact that a JSONObject keys are returned in reverse order.
Is there any way to recurse through a JSONObject in the correct order as appearing in JSON
String json;
JSONObject obj = new JSONObject(json)
Iterator<String> keys = json.keys() ---> order is reversed
I understand JSONObject is unordered, perhaps there is a way to order it????
JSON is of type below..and the keys start getting recursed from the bottom most styleHint tag
"sections": {
"1": {
"1": {
"1": {
"title": "xxx",
"text": "xxx",
"tags": {
"audience": {
"1": {
"name": "xxx",
"title": "xxx",
"id": "xxx"
}
},
"styleHint": {
"1": {
"name": "xxx",
"title": "xxx",
"id": "xxx"
}
}
}
},
"title": "xxx",
"text": "xxx",
"tags": {
"audience": {
"1": {
"name": "xxx",
"title": "xxx",
"id": "xxx"
}
},
"styleHint": {
"1": {
"name": "xxx",
"title": "xxx",
"id": "xxx"
}
}
}
},
"2": {
"title": "xxx",
"text": "xxx",
"tags": {
"audience": {
"1": {
"name": "xxx",
"title": "xxx",
"id": "xxx"
}
},
"styleHint": {
"1": {
"name": "xxx",
"title": "xxx",
"id": "xxx"
}
}
}
},
"title": "xxx",
"text": "xxx",
"tags": {
"audience": {
"1": {
"name": "xxx",
"title": "xxx",
"id": "xxx"
},
"2": {
"name": "xxx",
"title": "xxx",
"id": "xxx"
}
},
"styleHint": {
"1": {
"name": "xxx",
"title": "xxx",
"id": "xxx"
}
}
}
},
"2": {
"title": "xxx",
"text": "xxx",
"tags": {
"audience": {
"1": {
"name": "xxx",
"title": "xxx",
"id": "xxx"
}
},
"styleHint": {
"1": {
"name": "xxx",
"title": "xxx",
"id": "xxx"
}
}
},
"anchor":"xxx"
},
"3": {
"1": {
"title": "xxx",
"text": "xxx",
"tags": {
"audience": {
"tag": {
"name": "xxx",
"title": "xxx",
"id": "xxx"
}
},
"styleHint": {
"tag": {
"name": "xxx",
"title": "xxx",
"id": "xxx"
}
}
}
},
"title": "xxx",
"text": "xxx",
"tags": {
"audience": {
"1": {
"name": "xxx",
"title": "xxx",
"id": "xxxx"
}
},
"styleHint": {
"1": {
"name": "xx",
"title": "xxx",
"id": "xxxx"
}
}
}
}
}
How about that
Get your org.json.JSONObject source and change these
public ListIterator keys() {
ListIterator iter = new ArrayList(this.keySet()).listIterator();
return iter;
}
and
/**
* Construct an empty JSONObject.
*/
public JSONObject() {
this.map = new LinkedHashMap();
}
and
/**
* The map where the JSONObject's properties are kept.
*/
private final LinkedHashMap map;
and
public JSONObject(Map map) {
this.map = new LinkedHashMap();
if (map != null) {
Iterator i = map.entrySet().iterator();
while (i.hasNext()) {
Map.Entry e = (Map.Entry) i.next();
Object value = e.getValue();
if (value != null) {
this.map.put(e.getKey(), wrap(value));
}
}
}
}
I hope I don't burn in hell for that.