This is the first time i am using a YAML parser and I am currently stuck at this point
I have a config file which goes something like
Users
-Name:A
Id : x
Addr:10.0.0.1
-Name:B
Id :y
Addr:10.0.0.2
HomeAddress
City:bla bla
Country:bla bla
Office Address
City:abchd
Country:bha bha ba
So I thought the best way to parse it would be to have a list like this.
List<Map<String, obj>> Object = (List<Map<String, obj>>) yaml.load(input);
Objective was to access the object by specifying a string. Like Username A, I shld be able to obtain his id and IPAddr (This is the most important to me at the moment). But when I tried this declaration, I got an error like this
Exception in thread "main" java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to java.util.List
at Message.MessagePasser.<init>(MessagePasser.java:34)
Can someone please help me debug this. I am running by a deadline!!:(
The YAML parser seems to be returning a Map. So you should use it like this:
Map config = (Map) yaml.load(input);
Map usersConfig = config.get("Users");
Also what particular YAML parser are you using?
Update 1: If you look at the documentation, the load method either returns a List or Map depending on the contents of your YAML file. As your YAML file starts with a key-value mapping (Users) and not an array (-), the load method returns a Map which is the appropriate type to be returned in this case.
1) check the validity of your YAML here: http://instantyaml.appspot.com/
2) Your document should look like this: (mind the spaces !)
Users :
- Name : A
Id : x
Addr : 10.0.0.1
- Name : B
Id : y
Addr : 10.0.0.2
Related
The webservice: http://services.groupkt.com/country/search?text=lands has 16 records returned from a GET request. In the records, there is a parameter called 'name'. So, there are 16 names and each name has a unique value (country). My intention is to list all the 16 values of the 'name'parameter using java and the RESTassured library. I tried this:
Response response = RestAssured.get("http://services.groupkt.com/country/search?text=lands").andReturn();
String json = response.getBody().asString();
JsonPath jp = new JsonPath(json);
List<String> ls = from(response).getList("RestResponse.result.name");// The 'from' text displays an error
An error was seen on the 'from' text and it says: The method from(String) in the type RestTest is not applicable for the arguments (Response). I am not sure how to rectify this. Is there a simple way to create a list of all the values of the 'name' parameter?
Try replacing from(response) to from(jp). That should take care of the error you are getting.
The Response class (which is what the get() method returns) also supports jsonPath, so you could also refactor it to something like this:
List names= get("http://services.groupkt.com/country/search?text=lands").jsonPath().getList("RestResponse.result.name");
So I have been using jayway JSONPath to query JSON Objects much like the following:
{
"messageHeader" : {
"sentBy" : "someOne",
"userName" : "John Doe"
},
"payload" : []
}
And this is working fine for the most part, except now I wish to select the root level objects using the path $..* and preform separate tasks depending on the type of object present in the message, using their key/names as an identifier.
However, using said path, or $.* , will always produces a JSONArray much like this:
[{sentBy:someOne,userName:John Doe},[]]
The JSON objects appear to be anonymous, they have no keys. Is there anyway I can access the key for these objects directly as a String? If the data is not present, then why does the path: $.messageHeader.sentBy , work?
From README of the JsonPath :
When evaluating a path you need to understand the concept of when a
path is definite. A path is indefinite if it contains:
.. - a deep scan operator
?() - an expression
[, (, )] - multiple array indexes
Indefinite paths always returns a list (as represented by current JsonProvider).
This should explain the above phenomenon.
I'm trying to convert a large Map> to some JavaBean. The key of map corresponds to some property of JavaBean, and the value somehow is decoded to property value. So I decided to use some util for that, but don't know what will work. There are some requirements I have to this util (or framework):
all configuration must be in separate files
should be a possibility to map dynamic quantity of keys:
there is a map:
key | value
quan | n
key_1| value_1
key_2| value_2
........ | .............
key_n| value_n
where n - is any number
and the JavaBean has a List of some beans. They have a property. value_1, value_2, ... must be mapped in this property, and in the end there must be so much beans in list, as these keys and values in map.
3.. should be a possibility to set up custom decoder for property mapping, because in most cases the value in map is a List with 1 value, so I need to get the first item of list (if it's not empty).
4.. should be a possibility run some script to execute extraordinary mappings, for example:
there is a map, that is described in 2d point.
and the JavaBean has a property of type HashMap, where value_1 is mapped to Bean1 and some analogous value from input map is mapped to Bean2.
I've tried to use smooks, but when I've started, all these requirements were not clear yet and the smooks was something new, I haven't worked with it until now. So the smooks config doesn't contain the whole business-logic (because of second req.) and looks ugly, I don't like that. I can show the most ugliest fragment for 2d point:
<jb:bean beanId="javaBean" class="com.example.JavaBean" createOnElement="map">
<jb:wiring property="someBeans" beanIdRef="someBeanItems"/>
</jb:bean>
<jb:bean beanId="someBeanItems" class="java.util.ArrayList" createOnElement="map/entry">
<jb:wiring beanIdRef="someBeanItem"/>
</jb:bean>
<jb:bean beanId="someBeanItem" class="com.example.someBeanItem" createOnElement="map/entry">
<condition>map.quan[0]>0</condition>
<jb:expression property="property1">
index = map.quan[0]-1;
value = additionalProperties.property1_List[index];
map.quan[0] = map.quan[0] - 1;
return value;
</jb:expression>
</jb:bean>
Here "property1_List" is builded before executing smooks.
Now I look for something more nice and need your help: maybe you know how to make that better using smooks? Or what another frameworks for mapping can you recommend for my issue?
I have this entity - I'm trying to determine the type of its properties - in Google App Engine's internal data-types PREFERRED (as opposed to Java data types).
The below code is obviously simplified. In reality I do not know the entity's properties or anything else about it.
final DatastoreService dss = DatastoreServiceFactory.getDatastoreService();
final Query query = new Query("Person");
final PreparedQuery pq = dss.prepare(query);
for (Entity entity : pq.asIterable())
{
final Object property = entity.getProperty("some_property");
// Here I want to determine which data type 'property' represents - GAE-wise.
}
In App Engine's Java code I've found some hints:
DataTypeTranslator
DataTypeTranslator.typeMap (internal private member)
Property.Meaning.GD_PHONENUMBER
I'm unable to link those together into what I need - some sort of reflection.
I wish I was able to do something like this:
entity.getPropertyType("some_property");
Does anyone know better?
DataTypeTranslator source code here
Edit #1: <<
INGORE this one. It's me who put these postfixes (I was confused by the doc).
Here's more important info I've found.
I'm getting it in Eclipse' tool-tip mini-window when I point over an entity (one which I just fetched from the Datastore).
The Datastore seems to send it (this payload) as raw text which is nice, maybe I'll have to parse it (but, how do I get it from code LOL).
Pay attention to the types in here, it's written plain simple.
Here it is:
<Entity [Bird(9)]:
Int64Type:44rmna4kc2g23i9brlupps74ir#Int64Type = 1234567890
String:igt7qvk9p89nc3gjqn9s3jq69c = 7tns1l48vpttq5ff47i3jlq3f9
PhoneNumber:auih50aecl574ud23v9h4rfvt1#PhoneNumberType = 03-6491234
Date:k1qstkn9np0mpb6fp41cj6i3am = Wed Jul 20 23:03:13 UTC 2011
>
For example, property named String:igt7qvk9p89nc3gjqn9s3jq69c has the value of 7tns1l48vpttq5ff47i3jlq3f9 and it doesn't tell its type. Also property Date:k1qstkn9np0mpb6fp41cj6i3am.
Property named Int64Type:44rmna4kc2g23i9brlupps74ir has the value of "1234567890" and here it strictly mentions that the data type is of "Int64Type".
I'm searching for it too.
It's a bit of a hack, but at least my output includes the type (without needing a secret decoder ring). But my code is slightly different:
Query allusersentityquery = new Query();
allusersentityquery.setAncestor(userKey);
for (final Entity entity : datastore.prepare(allusersentityquery).asIterable()) {
Map<String, Object> properties = entity.getProperties();
String[] propertyNames = properties.keySet().toArray(
new String[properties.size()]);
for(final String propertyName : propertyNames) {
// propertyNames string contains
// "com.google.appengine.api.datastore.PostalAddress" if it is a Postal Address
}
}
There seems to be no documents about determining the Property Types here.
I have a XML file with many copies of table node structure as below:
<databasetable TblID=”123” TblName=”Department1_mailbox”>
<SelectColumns>
<Slno>dept1_slno</Slno>
<To>dept1_to</To>
<From>dept1_from</From>
<Subject>dept1_sub</Subject>
<Body>dept1_body</Body>
<BCC>dept1_BCC</BCC>
<CC>dept1_CC</CC>
</SelectColumns>
<WhereCondition>MailSentStatus=’New’</WhereCondition>
<UpdateSuccess>
<MailSentStatus>’Yes’</MailSentStatus>
<MailSentFailedReason>’Mail Sent Successfully’</MailSentFailedReason>
</UpdateSuccess>
<UpdateFailure>
<MailSentStatus>’No’</MailSentStatus>
<MailSentFailedReason>’Mail Sending Failed ’</MailSentFailedReason>
</ UpdateFailure>
</databasetable>
As it is not an efficient manner to traverse the file for each time to fetch the details of each node for the queries in the program, I used the nested hashmap concept to store the details while traversing the XML file for the first time. The structure I used is as below:
MapMaster
Key Value
123 MapDetails
Key Value
TblName Department1_mailbox
SelectColumns mapSelect
Key Value
Slno dept1_slno
To dept1_to
From dept1_from
Subject dept1_sub
Body dept1_body
BCC dept1_BCC
CC dept1_CC
WhereCondition MailSentStatus=’New’
UpdateSuccess mapUS
MailSentStatus ’Yes’
MailSentFailedReason ’Mail Sent Successfully’
UpdateFailure mapUF
MailSentStatus ’No’
MailSentFailedReason ’Mail Sending Failed’
But the problem I’m facing now is regarding retrieving the Value part using the nested Keys. For example,
If I need the value of Slno Key, I have to specify TblID, SelectColumns, Slno in nested form like:
Stirng Slno = ((HashMap)((HashMap)mapMaster.get(“123”))mapDetails.get(“SelectColumns”))mapSelect.get(“Slno”);
This is unconvinent to use in a program. Please suggest a solution but don’t tell that iterators are available. As I’ve to fetch the individual value from the map according to the need of my program.
EDIT:my program has to fetch the IDs of the department for which there is privilege to send mails and then these IDs are compared with the IDs in XML file. Only information of those IDs are fetched from XML which returned true in comparison. This is all my program. Please help.
Thanks in advance,
Vishu
Never cast to specific Map implementation. Better use casting to Map interface, i.e.
((Map)one.get("foo")).get("bar")
Do not use casting in your case. You can define collection using generics, so compiler will do work for you:
Map<String, Map> one = new HashMap<String, Map>();
Map<String, Integer> two = new HashMap<String, Integer>();
Now your can say:
int n = one.get("foo").get("bar");
No casting, no problems.
But the better solution is not to use nested tables at all. Create your custom classes like SelectColumns, WhereCondition etc. Each class should have appropriate private fields, getters and setters. Now parse your XML creating instance of these classes. And then use getters to traverse the data structure.
BTW if you wish to use JAXB you do not have to do almost anything! Something like the following:
Unmarshaller u = JAXBContext.newInstance(SelectColumns.class, WhereCondition.class).createUnmarshaller();
SelectColumns[] columns = (SelectColumns[])u.unmarshal(in);
One approach to take would be to generate fully qualified keys that contain the XML path to the element or attribute. These keys would be unique, stored in a single hashmap and get you to the element quickly.
Your code would simply have to generate a unique textual representation of the path and store and retrieve the xml element based on the key.