I have a very simple question...
In my Android app i'm forming a JSON string to send to my server... there are no error in my code, but Java (or Android) puts the values in a different order of mine and I don't know why...
I want to solve this issue, because I need to process that JSON string in the server to update some tables of my database... my PHP code in the server uses the same order I used in my app to decode the JSON string, but because of Android (or Java) that changes the order, I'm having troubles to update the tables...
Any ideas? Thanks in advance!
I'm talking about this:
In my app:
json_data.put("id_visit", visits.getString(visits.getColumnIndexOrThrow("id_visit")));
json_data.put("id_form", visits.getString(visits.getColumnIndexOrThrow("id_form")));
json_data.put("id_establishment", visits.getString(visits.getColumnIndexOrThrow("id_establishment")));
json_data.put("id_promoter", visits.getString(visits.getColumnIndexOrThrow("id_promoter")));
json_data.put("actual_date", visits.getString(visits.getColumnIndexOrThrow("actual_date")));
json_data.put("receiver", visits.getString(visits.getColumnIndexOrThrow("receiver")));
json_data.put("observations", visits.getString(visits.getColumnIndexOrThrow("observations")));
json_data.put("gps_coordinates", visits.getString(visits.getColumnIndexOrThrow("gps_coordinates")));
In the LogCat:
{
"id_promoter":"1",
"id_establishment":"5",
"id_visit":"1",
"receiver":"brenda lopez",
"gps_coordinates":"10.4905567 -66.8710966",
"actual_date":"2012-11-27",
"id_form":"1",
"observations":"observaciones"
}
As you can see, its not te same order! Why is this?
I apologize for not taking the time of checking if someone else already asked this, but I'm in a little hurry, so... Sorry!! xD
Object keys are not ordered in JSON. If you need a specific order, I suggest you use an array:
[
{"id_promoter":"1"},
{"id_establishment":"5"},
{"id_visit":"1"},
{"receiver":"brenda lopez"},
{"gps_coordinates":"10.4905567 -66.8710966"},
{"actual_date":"2012-11-27"},
{"id_formu":"1"},
{"observations":"observaciones"}
]
It's gross, but order is what arrays are for.
Another approach is to define an array with the key names in the desired order. Then you can use your original object structure but access it through keys defined by the array. This takes more coding, obviously, but it can also solve your problem.
Related
I am using Json Patch library to perfrom a Patch operation using REST. Now I have the follwoing json document:
{
"id":1,
"ref":{"r1":1,"r2":2}, // header level
"child":[
{
"childId":1,
"ref":{"cc1":1,"cc2":2} // line level
},
{
"childId":2,
"ref":{"cc3":2} // line level
}
]
}
Now As per Json Patch doc we at the header level we can update the ref r1 using the following path /ref/r1 .
Now I am trying to perform operation on the line level child ref. Since child is an array I can use the path /child/0/ref/cc1. But as can be seen from the path I have to specify the index also which is 0 in the previous case.
Now for API consumers asking them to give the index of the array become difficult. So is there any way to customize json patch so that we can bypass the index requirement or what are the other ways to handle this scenario?
I'm not an expert in JSON-Patch, i've just read about it.
from what i understood, is the most important part is to let the API consumers access to your JSON without giving them index,
I think hashmap would help in this case, by getting the index of each element and generate a specific ID for it, then you can save them in the hashmap list, each index has its own ID.
a sample:
HashMap<String, String> elementIndex = new HashMap<[UUID], [elementIndex]>();
you can choose whatever DataType you want, not necessary String
In this case it doesn't matter which index number, it is all about the fixed UUID.
So the path will be in this case /child/{UUID}/ref/cc1 also when you receive the path you can access the UUID and replace it with its elementIndex, now you have the correct path which is /child/0/ref/cc1
and if you want to know how to pass a dynamic value to a JSON Object, there are multiple ways to do it,
this question will help:
How to pass dynamic value to a JSON String, -Convert the JSONObject to String before-
NOTE: It is not necessary to replace it with index, you can do it the way you like could be.
And i believe there are better answers if someone knows more about JSON-patch.
i hope that was helpful, or at least gives you an idea about how to solve it.
Edit: Figured it out, check my posted answer if you're having similar issues.
I know there are several questions about this issue, but none of their solutions are working for me.
In my model class I have made sure to use List instead of Arraylist to avoid Firebase issues, but am still getting this error. It's a lot of code but most questions ask for all the code so I'll post it all.
TemplateModelClass.java
//
I've used this basic model successfully many times. For the
HashMaps<String, List<String>>,
the String is an incremented Integer converted to String. The List's are just Strings in a List. Here's some sample JSON from Firebase:
//
Formatted that as best as I could. If you need a picture of it let me know and I'll get a screenshot
And am getting this error, as stated in the title:
com.google.firebase.database.DatabaseException: Expected a Map while deserializing, but got a class java.util.ArrayList
The most upvoted question about this seems to have something to do with a problem using an integer as a key, but I think I've avoided that by always using an integer converted to a string. It may be interpreting it strangely, so I'll try some more stuff in the meantime. Thanks for reading!
Alright, figured it out. If anyone reading this has this problem and are using incremented ints/longs/whatever that get converted to strings, you must add some characters to the converted int. Firebase apparently converts these keys back into non-Strings if it can be converted.
For example, if you do something like this:
int inc = 0;
inc++; // 1
map.put(String.valueOf(inc), someList);
Firebase interprets that key as 1 instead of "1".
So, to force Fb to intepret as a string, do something like this:
int inc = 0;
inc++; // 1
map.put(String.valueOf(inc) + "_key", someList);
And everything works out perfectly. Obviously if you also need to read those Strings back to ints, just split the string with "[_]" and you're good to go.
The main issue is that you are using a List instead of a Map. As your error said, while deserializing it is expectig a Map but is found an ArrayList.
So in order to solve this problem youd need to change all the lists in your model with maps like this:
private Map<String, Object> mMapOne;
After changing all those fileds like this, you need also to change your public setters and getters.
Hope it helps.
I am using proto 3 (java) in my projects . I have some huge protobufs embedded with smaller messages . Is there a way I can acheive partial decoding of only few nested sub messages that I want to look at. The current issue I am having is I need to join this huge proto based record data with another records ,but my join are based on very small sub messages ,so I don't want to decode the entire huge protobuf and be able to only decode the nested message (string id) to join and then only decode the entire protobuf for the joined data.
I tried using the [lazy=true] tagging method , but I don't see any difference in generated code , also I tried benchmarking the deserialization time with and without the lazy key work and it didn't seem to affect at all . Is this feature by default on for all fields? Or is this even possible? I do see there are few classes LazyFields.java and test cases in the protobuf-github so I assume this feature has been implemented.
For those that happen to look at this conversation later and finding it hard to understand, here's what Marc's talking about:
If your object is something like
message MyBigMessage{
string id = 1;
int sourceType = 2 ;
And many other fields here, that would be expensive to parse .......
}
And you get a block of bytes that you have to parse. But you want to only parse messages from a certain source and maybe match a certain id range.
You could first parse those bytes with another message as:
message MyFilterMessage{
string id = 1; //has to be 1 to match
int sourceType = 2 ; //has to be 1 to match
And NOTHING ELSE here.......
}
And then, you could look at sourceType and id. If they match whatever you are filtering for, then, you could go and parse the bytes again, but this time, using MyBigMessage to parse the whole thing.
One other thing to know:
FYI: As of 2017, lazy parsing was disabled in Java (except MessageSet) according to this post:
https://github.com/protocolbuffers/protobuf/issues/3601#issuecomment-341516826
I dont know the current status. Too lazy to try to find out ! :-)
I want to work with Open Street Map (OSM). OSM keeps its data formats as flexible as possible by using key value pairs. I am developing an application for Android and I am going to send it a JSON string of OSM data. What should I do if I do not know what the JSON will look like in advance? What would be the best library?
Thanks for your help,
Chris
This may be what you are looking for
http://code.google.com/p/google-gson/
Cheers
First of all, you need to know if the JSON file contains an array or an object. If the first nonwhite space character is a [, it's an array, if it's a {, it's an object. Creating JSONArray when the first char is a { or vice versa will throw a Runtime Exception.
Second off all, once you have your JSONObject, you're going to want to get data from it. So you have to know the name of the keys to get the values, i.e.
myStreet = myJsonOjbect.getString("street name")
If you're not going to get data from it, what's the point of having the json file? Surely you can open the JSON in a Lint to see what the structure is.
hope this helps!
Hi I have some trouble with arrays in mongodb. To read a document with java is no problem but to read an array what is in a document is a problem. Lets say I have a collection myCol:
{"name": "lenny linux", "gender": "m", "computers": [{"name": "computer"}, {"name": "computer2"} {"name"...}]}
So there is an array with computers. I could read the whole document with
DBCollection myCol = getCollection(...);
BasicDBObject query = new BasicDBObject();
query.put(name, "lenny linux");
DBCursor cursor = myCol.find(query);
while (cursor.hasNext()) {
System.out.print(cursor.next());
}
But I just need the names of the computers, so I have to read somehow the array. Dont get this array stuff in mongodb. And also what if I would like to delete something from a mongodb array? Its not the same as to delete a normal document... thank you for any help!
Edit: If im reading the mongodb page: http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-ValueinanArray I really dont get it. They have there an array of colors and then they are reading red like this:
db.things.find({ colors :"red" });
Why would I do this? If I want to read an array to know whats inside the array. The user dont know that there is a "red" or blue or whatever. Maybe the array colors is empty? Then I get back a null, 0 or whatever and if there are 4 colors then give me these colors, print it out. I dont have any other examples...im sorry for my bad english.
Edit2:
Ok so the new solution for me is to get the whole document where name == lenny linux (like at the first time in my code) and then to parse this document with an extern JSON parser like json-simple. Well maybe thats not the best solution, because the best solution would be to get the stuff in the array without other libs just using the mongolib... but ok its working :) If somebody knows an easier way just post it here. Thank you.
And also what if I would like to delete something from a mongodb
array? Its not the same as to delete a normal document.
http://www.mongodb.org/display/DOCS/Updating explains 2 ways:
$set: to replace the current array with a new one (fetch the previous array, remove an element or two, and update with $set)
db.users.update({name : "lenny linux"}, {$pull : { computers : { name : "computer2" } }}, false, false) to remove all elements from the array computers that have name 'computer2'.
When reaching into an array with objects (named elements), you want to use the dot notation to reach into the array.
db.myColl.find({'computers.name':'computer'});
http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-ValueinanArray
as for removing items from an array, you want to look at the $pop and $pull update functions
http://www.mongodb.org/display/DOCS/Updating
Since I was dealing with this problem in Java, and your code is in Java, here is the solution ... in java.
Basically when you get(key) a MongoDB array, it returns a com.mongodb.BasicDBList object that you can get an iterator for.
In my code, I query documents that look like this:
{
"_id": ObjectID("52d60db91f3aa664410bcde5"),
"owner": "Amy",
"trusted": [
"amy",
"paul",
"randy"
]
}
And when I ever need to find the trusted people of this document, I use ((BasicDBList) doc.get("trusted")).listIterator();
DBObject doc = collection.findOne(new BasicDBObject("owner", "Amy"))
ListIterator<Object> trustedList = ((BasicDBList) doc.get("trusted")).listIterator();
while(trustedList.hasNext()){
Object nextItem = trustedList.next();
System.out.println(nextItem.getClass()); // String
// Here I handle what to do to each name.
// I could add them to an ArrayList<String> if I needed
updateTrustee((String)nextItem);
}
I came to this solution using a few System.out.println(Object.getClass())s to know what classes I needed to cast.
The question he is asking is how does one return ALL the elements found in an array stored in a Mongo collection without knowing precisely how many or what these elements might be. You are not performing a query against a known value, rather you are simply asking for a dump of what is in the Mongo array. For example, if your Mongo array name is "colors", simply do the following:
#colors = #{$record->{colors}};
Now you have all the colors in a Perl array for you to play with.
Enjoy!