I am working on velocty and java, I was to take values from an json file (which I took using recursion of JSON OBjects and storing path of recursion(See context below to get idea)
String hhh="I am a ${root.primaryApplicant.firstName} ${firstName} ";
Velocity.init();
VelocityContext vm=new VelocityContext();
for(String m : mp.keySet())
{
vm.put(m,mp.get(m));
}
StringWriter w = new StringWriter();
Velocity.evaluate( vm, w, "mystring", forma );
The map mp is obtained from a json file
{
"id": 45288,
"code": null,
"name": null,
"external": false,
"leadReferenceId": "APPID1573716175142",
"createdBy": null,
"createdDate": "2017-10-26T12:14:17.000Z",
"agentName": null,
"ipAddress": null,
"applicationType": "HOME",
"loanType": "HOME",
"applicantType": {
"id": 269,
"code": "Single",
"name": "Single",
"external": false
},
"relationship": null,
"primaryApplicant": {
"id": 45289,
"code": null,
"name": null,
"external": false,
"existingCustomer": null,
"customerId": null,
"partyRoleType": {
"id": 348,
"code": "0",
"name": "PRIMARY",
"external": false
},
"partyRelationshipType": null,
"salutation": {
"id": 289,
"code": "MR",
"name": "Mr",
"external": false
},
"firstName": "Anuj",
"middleName": "",
"lastName": "singh",
"dateOfBirth": "1986-12-11T18:30:00.000Z",
"genderType": {
using a debugger the context of vm contains
"root.primaryApplicant.firstName" -> "Anuj"
"firstName" -> "Anuj"
after Velocity evaluate I get
"I am a ${root.primaryApplicant.firstName} Anuj ";
i am assuming it cant replace keys with . in between.
Is there any better way to populate the string
----------------
The velocity file has a "root.*" specified and since I cant edit those, I am using the following recursion program to get the keys
private static void rexuse(String a,Map<String, Object> mp,JSONObject js,String parent) throws JSONException {
Iterator<String> keys = js.keys();
while(keys.hasNext()) {
String key = keys.next();
if(key.equals("name"))
{
mp.put(parent,js.get(key));
}
if (js.get(key) instanceof JSONObject) {
rexuse(a+"."+key,mp,js.getJSONObject(key),key);
}
else
{
if(!mp.containsKey(key) ||( mp.containsKey(key) && mp.get(key)==null))
mp.put(key, js.get(key));
mp.put(a+"."+key, js.get(key) );
}
}
}
where a is the prefix and called the above using
String a="root";
rexuse(a,mp,js,"root");
There is an inconsistency, here.
With the Java initialization code you give, the Velocity template should contain:
${primaryApplicant.firstName}
If you want to use ${root.primaryApplicant.firstName}, then the other reference should also be prefixed by root, as in ${root.firstName}, and the Java context initialization code should be:
vm.put("root", mp);
But in both cases you must also check that the json library you are using provides a Json object with a generic getter, so that the 'dot' operator will recursively call the Java method get(<fieldname>) on the json object. There are tons of those.
Related
I am trying to call an API using Retrofit in android. For this API I need the input parameter JSON object in proper sequence.
Only if I have the json in required sequence I get successful response from the API, otherwise it gives an error. To handle this issue I got one solution that is to first create a LinkedHashMap of input parameter then create the JSON of that LinkedHashMap. This way I'm acheaving the response from api.
but right now im confused how to create linkedHash map for below json
{
"RequestXml": {
"Authenticate": {
"InterfaceCode": "1",
"InterfaceAuthKey": "AirticketOnlineWebSite",
"AgentCode": "MOS0000001",
"Password": "KGBW5P"
},
"BookTicketRequest": {
"TrackNo": "0$182967|4|1AO",
"MobileNo": "9099776464",
"AltMobileNo": "9898989898",
"Email": "abc#gmail.com",
"Address": "Test",
"ClientRequestID": "",
"Passengers": {
"Passenger": [
{
"PaxSeqNo": "1",
"Title": "Mr",
"FirstName": "Savan",
"LastName": "Test",
"PassengerType": "A",
"DateOfBirth": "01/12/1992",
"PassportNo": "RTTTTGGBGB56356",
"PassportExpDate": "01/12/2024",
"PassportIssuingCountry": "IND",
"NationalityCountry": "IND"
}
]
},
"Segments": {
"Segment": [
{
"TrackNo":"0$182967|4|1AO",
"SegmentSeqNo": "1",
"AirlineCode": "UK",
"FlightNo": "888",
"FromAirportCode": "BOM",
"ToAirportCode": "DEL",
"DepDate": "30/09/2019",
"DepTime": "14:00",
"ArrDate": "30/09/2019",
"ArrTime": "16:00",
"FlightClass": "E",
"MainClass": "Y"
}
]
},
"AdditionalServices": {
},
"TotalAmount": "4735",
"MerchantCode": "PAY9zJhspxq7m",
"MerchantKey": "eSpbcYMkPoZYFPcE8FnZ",
"SaltKey": "WHJIIcNjVXaZj03TnDme",
"IsTicketing": "Yes"
}
}
}
I have the following JSON data:
JSON:
[{
"valInternalCode": "NE",
"valMinimumInputString": "NE",
"valExternalRepresentation": "Northeast",
"valActionCode1": "1",
"valActionCode2": null,
"valActionCode3": null,
"valActionCode4": null,
"id": {
"valcodeId": "X.LOCATION",
"pos": 1
},
"uniqueId": "X.LOCATION-1",
"caption": "Northeast"
}, {
"valInternalCode": "NW",
"valMinimumInputString": "NW",
"valExternalRepresentation": "Northwest",
"valActionCode1": "1",
"valActionCode2": null,
"valActionCode3": null,
"valActionCode4": null,
"id": {
"valcodeId": "X.LOCATION",
"pos": 2
},
"uniqueId": "X.LOCATION-2",
"caption": "Northwest"
}
I am able to parse it and create a Map from the data like so:
Gson gson = new Gson();
Type collectionType = new TypeToken<Collection<Map>>(){}.getType();
Collection<Map> dataCollection = gson.fromJson(jsonString.toString(), collectionType);
I can then iterate through it and get a value that I need using the Key like so:
iterator.next().get("valInternalCode");
What I am struggling with is how to get something that is inside of the id field:
"id": {
"valcodeId": "X.LOCATION",
"pos": 2
},
I am using Hibernate to get the data from a non normalized Oracle database (that is why hibernate creates the id field the way it does)
EDIT:
My attempt at an ugly way of doing it. Basically looping within the loop:
while (valIterator.hasNext()) {
Map currentVal = valIterator.next();
String valId = "";
Collection<Map> idVal = (Collection<Map>) currentVal.get("id");
Iterator<Map> valIdIterator = idVal.iterator();
while (valIdIterator.hasNext()) {
Map valIdCurrentVal = valIdIterator.next();
valId = valIdCurrentVal.get("valcodeId").toString();
}
}
Getting a ClassCastException when I try to cast currentVal.get("id") to a Collection
According to the GeoJson spec (https://www.rfc-editor.org/rfc/rfc7946), features with different sets of properties are allowed, but when i am processing my GeoJson file using FeatureJSON.readFeatureCollection i get an error saying no such attribute:tract_boundary.
here's the part of my file showing the two features with different properties (notice the attribute name "tract_boundary" appears in the second feature properties):
{
"type": "Feature",
"properties": {
"clu_identifier": "3ecc54fc-5077-11d6-8e82-00065b4a19c0",
"clu_alt_id": "{5626C60F-23B1-4172-BCFA-842EBDEE776F}",
"data_source": "danna.steffens",
"clu_status": null,
"tract_number": "768",
"last_change_date": 1352656579000,
"last_chg_user_nm": null,
"creation_date": 1113921633000,
"admin_state": "20",
"clu_calculated_acreage": 152.41,
"OBJECTID": 582,
"cropland_indicator_3CM": 1,
"edit_reason": null,
"GlobalId": "{DE7A11AA-BFB6-4DFE-A1D7-D795D7DD7990}",
"SHAPE_STArea__": 1012852.6422872,
"state_code": "20",
"cdist_fips": "2001",
"highly_erodible_land_type_code": "NHEL",
"admin_county": "171",
"clu_classification_code": "2",
"sap_crp": null,
"farm_number": "4384",
"SHAPE_STLength__": 4161.19756459,
"ESRI_OID": 530,
"clu_number": "1",
"data_source_site_identifier": null,
"comments": " ",
"county_code": "171"
},
"geometry": {...
},
{
"type": "Feature",
"properties": {
"farm_number": "4384",
"admin_state": "20",
"tract_number": "5468",
"admin_county": "171",
"tract_boundary": true
},
"geometry": {...
}
Any ideas?
You can get the "full" schema by calling org.geotools.geojson.feature.FeatureJSON.readFeatureCollectionSchema(Object, boolean) with the 2nd argument set to false so that the whole collection is read rather than just the first item. Then you can set the FeatureType of your features correctly.
I have Json data like this:
{
"_id": "123",
"transaction": {
"className": "ExpenseReport",
"id": "789",
"createdBy": {
"firstName": "Donald",
"lastName": "Morgan",
"address": {
"street1": "1362 Woodlawn Lane",
"street2": "Suite #100805",
"place": {
"city": "Darien",
"state": "CA",
"country": "USA",
"number": "OBJ-4823478",
"createdBy": "Brett Wright"
},
"zip": 88884,
"number": "OBJ-5740231",
"createdBy": "Brett Wright"
},
"number": "OBJ-3561551",
"createdBy": "Brett Wright"
},
"score": 12,
"reasonCodes": [
"these",
"are",
"strings"
]
}
}
I want a subset of this data after excluding some properties, say something like this:
{
"_id": "123",
"transactionType": "EXPENSE_REPORT",
"transaction": {
"className": "ExpenseReport",
"id": "789",
"createdBy": {
"firstName": "Donald",
"lastName": "Morgan",
"address": {
"street1": "1362 Woodlawn Lane",
"street2": "Suite #100805",
"place": {
"city": "Darien",
"state": "CA",
"country": "USA"
},
"createdBy": "Brett Wright"
},
"createdBy": "Brett Wright"
},
"score": 12
}
}
Now one way would be to deserialize the original json data into a POJO, use Jackson Views to annotate the required properties, and then serialize the same POJO again to get the Json data without the properties.
But I want to achieve something like this WITHOUT DESERIALIZING the Json data, say by just parsing the json data and removing the key-value pairs if they are not found in a collection. Is anyone aware of any library that does that?
Jackson allows you to do only the parsing step using ObjectMapper.readTree()
JsonNode root = om.readTree(input);
The resulting JsonNodes are mutable, so something like this does the job:
ObjectNode place = (ObjectNode)(root.findPath("transaction")
.findPath("createdBy")
.findPath("address")
.findPath("place")
);
place.remove("number");
This is --unfortunately-- not too nice, but can be easily wrapped into a generic method that takes a property path:
void deleteProperty(JsonNode root, List<String> propPath)
{
JsonNode node = root;
for (String propName: propPath.subList(0, propPath.size() - 1)) {
node = node.findPath(propName);
}
// completely ignore missing properties
if ((! node.isMissingNode()) && (! node.isEmpty())) {
if (node instanceof ObjectNode) {
final ObjectNode parent = (ObjectNode)node;
parent.remove(propPath.get(propPath.size() - 1));
}
}
}
It is then possible to write out the modified node tree using writeTree().
There is also the property filter API. Unfortunately while it is easy to filter out individual properties with it, it is non-trivial to use it for property paths. For example, in your case, the trivial filter can only filter out all createdBy properties.
This question already has answers here:
How to parse JSON in Java
(36 answers)
Closed 5 years ago.
I'm trying to parse an output from a server that looks like this:
{
"GetFolderFilesByZoneResult": [
{
"ID": 98748,
"CreatedBy": "",
"UpdatedBy": "none",
"CreatedDate": "\/Date(1308273033620+0100)\/",
"UpdatedDate": "\/Date(1308303003770+0100)\/",
"CommentCount": 0,
"Key": "",
"Enabled": true,
"MimeType": "video",
"Votes": 2,
"TotalRating": 0,
"AllowComments": true,
"ViewCount": 323,
"ReleaseDate": "\/Date(1308273000000+0100)\/",
"ExpireDate": "\/Date(4102444800000+0000)\/",
"Author": "",
"Size": 133799936,
"Tag1": "",
"Tag2": "",
"Tag3": "",
"RecycleBin": false
},
{
"ID": 99107,
"CreatedBy": "",
"UpdatedBy": "none",
"CreatedDate": "\/Date(1308583412520+0100)\/",
"UpdatedDate": "\/Date(1308583564007+0100)\/",
"CommentCount": 0,
"Key": "",
"Enabled": true,
"MimeType": "video",
"Votes": 0,
"TotalRating": 0,
"AllowComments": true,
"ViewCount": 33,
"ReleaseDate": "\/Date(1308583380000+0100)\/",
"ExpireDate": "\/Date(4102444800000+0000)\/",
"Author": "",
"Size": 47955968,
"Tag1": "",
"Tag2": "",
"Tag3": "",
"RecycleBin": false
}
]
}
I'm trying to use Java org.json to parse it, but I don't have any experience with JSON/org.json, so I'm having a little trouble. How can I parse this?
1) Assuming you have the JSON libraries on your path (from www.json.org), it's pretty easy.
import org.json.JSONTokener;
...
URI uri = new URI("http://someserver/data.json");
JSONTokener tokener = new JSONTokener(uri.toURL().openStream());
JSONObject root = new JSONObject(tokener);
From there, you can address the various parts of the JSON object. Take a look at the Javadocs for the specifics.
https://developer.android.com/reference/org/json/package-summary.html
Here is the most universal solution, which allows to parse any JSON type into appropriate Java type:
Object json = new JSONTokener(response).nextValue();
Then you can determine resulting type and handle it appropriately.
I'd pass it
map<String, Object>
loaded with
map<String, Object>
in the object field.
Basically recreating the hierarchy of your java classes inside of a large map.
Example :
return ( Map<"GetFolderFilesByZoneResult", Map<"Result1", (object by id 98748) | "Result2", (object by id 99107) | "Result3", etc.
JSON will return that big map very pretty like, and programmatically it's easier to do then lists.