I am trying to compare two ArrayList< Map< String, Object>> objects but the problem is that I need to compare them in different app sessions. So I am saving the first ArrayList in SharedPreferences after converting it to String using Gson. Then I query the string in next session to compare it. I tried converting it back to ArrayList then comparing it with the list generated during the new session. Also tried converting the new list into json and then comparing both texts. But the result is same. Below is the relevant code:
Declaration:
ArrayList<Map<String, Object>> tweetMapArray = new ArrayList<>();
Then in some method :
List<twitter4j.Status> statuses = twitter.getUserTimeline(params[0], new Paging(1, 200));
tweetMapArray.clear(); // I am also reusing it
for (twitter4j.Status status : statuses) {
Map<String, Object> valuesToPutInMarker = new HashMap<>();
valuesToPutInMarker.put("id", status.getId());
valuesToPutInMarker.put("status", status.getText());
tweetMapArray.add(valuesToPutInMarker);
}
Now saving tweetMapArray in SharedPreferences:
String jsonStr = gson.toJson(tweetMapArray);
editor = configData.edit();
editor.putString("tweetData", jsonStr);
editor.apply();
Querying data:
private boolean seeIfTheDataIsNew() {
String dataFromSharedPreferences = configData.getString("tweetData", null);
Type collectionType2 = new TypeToken<ArrayList<Map<String, Object>>>() {
}.getType();
ArrayList<Map<String, Object>> oldTweets = gson.fromJson(dataFromSharedPreferences, collectionType2);
String jsonStr = gson.toJson(tweetMapArray);
return jsonStr.equalsIgnoreCase(dataFromSharedPreferences);
// OR
return !(oldTweets.containsAll(tweetMapArray) && tweetMapArray.containsAll(oldTweets));
}
Here, both methods in last two lines return true. In the testing sample, they should return false.
Related
I used HashMap to store data which I received using API. After that, I used SharedPreferences to store the received HashMap data. Storing part is done. I can see the number of records which I wanted to store using SharedPreferences.
Here is the code to save data:
if (result != null && result.length() > 0)
{
for (int j = 0; j < result.length(); j++)
{
JSONObject resultObj = result.getJSONObject(j);
String label_id = resultObj.getString("label_id");
String arabic = resultObj.getString("arabic");
String english = resultObj.getString("english");
String key = resultObj.getString("key");
//Create a new model and set the received value
LabelModel labelModel = new LabelModel();
labelModel.setLabelId(label_id);
labelModel.setArabic(arabic);
labelModel.setEnglish(english);
labelModel.setKey(key);
int label = Integer.parseInt(label_id);
//Put the value
map.put(label, labelModel);
}
}
//With the below line, I stored the hashMap data using SharedPreferences
Pref.setValue(mActivity, AppPrefrences.PREF_LABELS, map);
After the above steps, I followed this set of code to set and get the value from SharePreferences, which I stored in application using SharedPreferences.
For that, I used this below code:
public static String PREF_LABELS ="labels";
public static void setValue(#NonNull Context context, String key, Object obj) {
Pref.openPref(context);
Editor prefsPrivateEditor = Pref.sharedPreferences.edit();
prefsPrivateEditor.putString(key, String.valueOf(obj));
prefsPrivateEditor.commit();
prefsPrivateEditor = null;
Pref.sharedPreferences = null;
}
#Nullable
public static String getValue(#NonNull Context context, String key, Object obj) {
Pref.openPref(context);
String result = Pref.sharedPreferences.getString(key, String.valueOf(obj));
Pref.sharedPreferences = null;
return result;
}
Now, I am trying to retrieve the data which I stored in SharedPreferences.
Here is the code I used to retrieve the data:
String labels = Pref.getValue(mActivity, AppPrefrences.PREF_LABELS, "");
When I debug the app, I get values in Labels below format. The same number of records I received.
The format goes like this:
{572=com.*****.landlord.model.LabelModel#23a282e, 598=com.*****.landlord.model.LabelModel#c954fcf, 590=com.*****.landlord.model.LabelModel#2fe3d5c, 103=com.*****..........}
How can I get the each data from this format?
There is no support for HashMap in SharedPreferences. So, you can't save the HashMap by converting it to a string directly, but you can convert it to JSON string. You can use google-gson in this case. Something like this:
First, include the dependency:
compile 'com.google.code.gson:gson:2.8.2'
Saving from HashMap object to preference:
Editor prefsEditor = mPrefs.edit();
Gson gson = new Gson();
String json = gson.toJson(map);
prefsEditor.putString("YourHashMap", json);
prefsEditor.commit();
Get HashMap object from preference:
Gson gson = new Gson();
String json = mPrefs.getString("YourHashMap", "");
HashMap map = gson.fromJson(json, HashMap.class);
Instead convert the map to gson String and store it in preference like this
//convert to string using gson
Gson gson = new Gson();
String mapString = gson.toJson(map);
//save this in the shared prefs
SharedPreferences prefs = getSharedPreferences("test", MODE_PRIVATE);
prefs.edit().putString("yourkey", mapString).apply();
//get from shared prefs in gson and convert to maps again
String storedHashMapString = prefs.getString("yourkey",null);
java.lang.reflect.Type type = new TypeToken<HashMap<String, String>>(){}.getType();
//Get the hashMap
HashMap<String, String> map = gson.fromJson(storedHashMapString, type);
You are getting {572=com.*****.landlord.model.LabelModel#23a282e, 598=com.*****.landlord.model.LabelModel#c954fcf, 590=com.*****.landlord.model.LabelModel#2fe3d5c, 103=com.*****..........} this because Object default toString() method use hashcode.
Storing complex object in SharedPreference is not recommended. SharedPreference don't support HashMap link.
For storing simple object you have to convert the object into String using toString() method.
You can use Gson for converting object to String and that will be a easy solution.
You can also use ObjectOutputStream to write it to the internal memory check this link
You should cast lables string into hashmap object This is one solution. If you want to make it more generic, you can us StringUtils library.
String value = "{first_name = mohit,last_name = mathur,gender = male}";
value = value.substring(1, value.length()-1); //remove curly brackets
String[] keyValuePairs = value.split(","); //split the string to creat key-value pairs
Map<String,String> map = new HashMap<>();
for(String pair : keyValuePairs) //iterate over the pairs
{
String[] entry = pair.split("="); //split the pairs to get key and value
map.put(entry[0].trim(), entry[1].trim()); //add them to the hashmap and trim whitespaces
}
For example, you can switch
value = value.substring(1, value.length()-1);
to
value = StringUtils.substringBetween(value, "{", "}");
and after that
You should cast value in LabelModel
like
LabelModel labels = map.get("598");
SharedPreference doesn't support store map object. https://developer.android.com/reference/android/content/SharedPreferences.Editor.html. So your code just store data obj.toString, that why you see result in debug. If you want to store a map, you can store as json and use put string.
I have a String with this format (it's a List of Map assigned to a string var)
[{code=1, data=Male} , {code=2, data=Female}]
.. how can I parse the above string back to list of map.. without using any String.split function (cause it is prone to error)
here is the code I've tried.. but with split function..
if(!string.equals("")){
String[] listArray = string.split(DELIMITER);
for (int i=0;i<listArray.length;i++) {
String val=listArray[i];
val = val.replaceAll("[\\{\\}]", "");
//Gets the value from DATA key
if(val.split(EQDELIMITER)[0].trim().equalsIgnoreCase("DATA")){
try{
map.put("DATA", val.split(EQDELIMITER)[1]);
}catch(IndexOutOfBoundsException e){
map.put("DATA", "");
}
}
//Gets the value from CODE key
if(val.split(EQDELIMITER)[0].trim().equalsIgnoreCase("CODE")){
try{
map.put("CODE", val.split(EQDELIMITER)[1]);
}catch(IndexOutOfBoundsException e){
map.put("CODE", "");
}
}
if (map != null && map.size() >= 2) {
//add map to codeList
codeList.add(map);
map = new HashMap<String,Object>();
}
}
}
If you are flexible enough to use a library, then Use google's GSON
Map map = gson.fromJson(jsonString, Map.class);
As you want a list of Map, wo you can also use TypeToken
List<Map<E,V>> list= new Gson().fromJson(jsonString,
new TypeToken<List<Map<E, V>>() {}.getType());
replace E, V with actual types.
Why can't you go for object Mapper..?(org.codehaus.jackson.map.ObjectMapper)
it would be something like this...
ObjectMapper mapper= new ObjectMapper();
Map<Integer,String> map = mapper.readValue(yourString,org.codehaus.jackson.type.TypeReference.TypeReference<Map<Integer,String>>() {
});
I have JSON value like below,
{ "emp_id": 1017,
"emp_name": "karthik Y",
"emp_designation": "Manager",
"department": "JavaJson",
"salary": 30000,
"direct_reports":
[
"Nataraj G",
"Kalyan",
"Mahitha"
]
}
HashMap < String, String[] >input1 = new HashMap < String, String[] >();
input1.put("empid","1017");
input1.put("emp_name","karthik");
input1.put("emp_designation","manager");
input1.put("salary","30000");
now I want to add next array that is direct_report to put as next key and value(entire array shoud be come one key and value). Someone please help out.
Hashmap is a key/value storage, where keys are unique. You can convert your JSON to string and then store it as a value to the hashmap. For example something like below:
public static void main(String[] args) {
String json = "{ \"emp_id\": 1017,"
+ "\"emp_name\": \"karthik Y\","
+ "\"emp_designation\": \"Manager\","
+ "\"department\": \"JavaJson\","
+ "\"salary\": 30000,"
+ "\"direct_reports\": ["
+ "\"Nataraj G\","
+ "\"Kalyan\","
+ "\"Mahitha\"]}";
HashMap<String, String> jsonStore = new HashMap<String, String>();
jsonStore.put("myJson", json);
System.out.println(jsonStore.get("myJson"));
}
You need can also use the 'org.json' library to
Create JSON object manually
Convert existing JSONObject to String representation
Convert JSON string to JSONObject
You can also have the following solution:
JSONObject jsonObject = new JSONObject();
jsonObject.put("empt_id", 1017);
jsonObject.put("emp_name", "karthik");
HashMap<String, JSONObject> jsonObjectStore = new HashMap<String, JSONObject>();
jsonObjectStore.put("myJsonObject", jsonObject);
HashMap<JSONObject, String> jsonObjectStore2 = new HashMap<JSONObject, String>();
jsonObjectStore2.put(jsonObject, "myJson");
Make sure that you download the org.json jar file and put it in your classpath to be able to use the JSONObject. You can download the jar from here.
In order to put each of those values into map as single key/value entry. You have mentioned it yourself, it should work without any problem. See below methods:
Method 1
Everything in Java is Object, String inherits Object, String[] inherits object. You can have the following solution:
HashMap<String, Object> myObjectStore4 = new HashMap<String, Object>();
String[] directReports4 = new String[]{"Natraj G", "Kalyan", "Mahitha"};
myObjectStore4.put("emp_id", new String("123"));
myObjectStore4.put("emp_name", new String("Raf"));
// others ....
myObjectStore4.put("directReports", directReports4);
Method 2
To store the fields as key/value and if you can afford converting the array to String (which represents all array elements comma separated then use this method).
HashMap<String, String> myObjectStoreTwo = new HashMap<String, String>();
String[] directReports2 = new String[]{"Natraj G", "Kalyan", "Mahitha"};
myObjectStoreTwo.put("emp_id", "123");
myObjectStoreTwo.put("emp_name", "Raf");
myObjectStoreTwo.put("salary", "222");
//Converts array to comma separated String
myObjectStoreTwo.put("directReports",Arrays.toString(directReports2));
Method 3
In the expense of having Hash Map to store String key and Array value. You have to put other elements as array too.
HashMap<String, String[]> myObjectStore3 = new HashMap<String, String[]>();
String[] directReports3 = new String[]{"Natraj G", "Kalyan", "Mahitha"};
myObjectStore3.put("emp_id", new String[]{123 + ""});
myObjectStore3.put("salary", new String[]{32312 + ""});
myObjectStore3.put("directReports", directReports3);
Use a jackson ObjectMapper. Try if this works
String json = "{....}"
HashMap<String,Object> mappedVals = new ObjectMapper().readValue(
json ,
new TypeReference<HashMap<String,Object>>() {
});
I have a JSON string that I get from a database which contains repeated keys. I want to remove the repeated keys by combining their values into an array.
For example
Input
{
"a":"b",
"c":"d",
"c":"e",
"f":"g"
}
Output
{
"a":"b",
"c":["d","e"],
"f":"g"
}
The actual data is a large file that may be nested. I will not know ahead of time what or how many pairs there are.
I need to use Java for this. org.json throws an exception because of the repeated keys, gson can parse the string but each repeated key overwrites the last one. I need to keep all the data.
If possible, I'd like to do this without editing any library code
As of today the org.json library version 20170516 provides accumulate() method that stores the duplicate key entries into JSONArray
JSONObject jsonObject = new JSONObject();
jsonObject.accumulate("a", "b");
jsonObject.accumulate("c", "d");
jsonObject.accumulate("c", "e");
jsonObject.accumulate("f", "g");
System.out.println(jsonObject);
Output:
{
"a":"b",
"c":["d","e"],
"f":"g"
}
I want to remove the repeated keys by combining their values into an array.
Think other than JSON parsing library. It's very simple Java Program using String.split() method that convert Json String into Map<String, List<String>> without using any library.
Sample code:
String jsonString = ...
// remove enclosing braces and double quotes
jsonString = jsonString.substring(2, jsonString.length() - 2);
Map<String, List<String>> map = new HashMap<String, List<String>>();
for (String values : jsonString.split("\",\"")) {
String[] keyValue = values.split("\":\"");
String key = keyValue[0];
String value = keyValue[1];
if (!map.containsKey(key)) {
map.put(key, new ArrayList<String>());
}
map.get(key).add(value);
}
output:
{
"f": ["g"],
"c": ["d","e"],
"a": ["b"]
}
In order to accomplish what you want, you need to create some sort of custom class since JSON cannot technically have 2 values at one key. Below is an example:
public class SomeClass {
Map<String, List<Object>> values = new HashMap<String, List<Object>>();
public void add(String key, Object o) {
List<Object> value = new ArrayList<Object>();
if (values.containsKey(key)) {
value = values.get(key);
}
value.add(o);
values.put(key, value);
}
public JSONObject toJson() throws JSONException {
JSONObject json = new JSONObject();
JSONArray tempArray = null;
for (Entry<String, List<Object>> en : values.entrySet()) {
tempArray = new JSONArray();
for (Object o : en.getValue()) {
tempArray.add(o);
}
json.put(en.getKey(), tempArray);
}
return json;
}
}
You can then retrieve the values from the database, call the .add(String key, Object o) function with the column name from the database, and the value (as the Object param). Then call .toJson() when you are finished.
Thanks to Mike Elofson and Braj for helping me in the right direction. I only wanted to have the keys with multiple values become arrays so I had to modify the code a bit. Eventually I want it to work for nested JSON as well, as it currently assumes it is flat. However, the following code works for what I need it for at the moment.
public static String repeatedKeysToArrays(String jsonIn) throws JSONException
{
//This assumes that the json is flat
String jsonString = jsonIn.substring(2, jsonIn.length() - 2);
JSONObject obj = new JSONObject();
for (String values : jsonString.split("\",\"")) {
String[] keyValue = values.split("\":\"");
String key = keyValue[0];
String value = "";
if (keyValue.length>1) value = keyValue[1];
if (!obj.has(key)) {
obj.put(key, value);
} else {
Object Oold = obj.get(key);
ArrayList<String> newlist = new ArrayList<String>();
//Try to cast as JSONArray. Otherwise, assume it is a String
if (Oold.getClass().equals(JSONArray.class)) {
JSONArray old = (JSONArray)Oold;
//Build replacement value
for (int i=0; i<old.length(); i++) {
newlist.add( old.getString(i) );
}
}
else if (Oold.getClass().equals(String.class)) newlist = new ArrayList<String>(Arrays.asList(new String[] {(String)Oold}));
newlist.add(value);
JSONArray newarr = new JSONArray( newlist );
obj.put(key,newarr);
}
}
return obj.toString();
}
My ArrayList<HashMap<String, String>> songslist has no values in it. In my doInBackground method i have for-loop that should fill this ArrayList. The Strings "id", "interpret"... have also values in it. Where is the problem? Here the code:
JSONArray charts = json.getJSONArray(TAG_CHARTS);
// looping through All Products
for(int i=0;i<charts.length();i++) {
JSONObject json_data = charts.getJSONObject(i);
String id = json_data.getString(TAG_ID);
String interpret = json_data.getString(TAG_INTERPRET);
String titel = json_data.getString(TAG_TITEL);
String album = json_data.getString(TAG_ALBUM);
String albumcover = json_data.getString(TAG_ALBUMCOVER);
String likes = json_data.getString(TAG_LIKES);
HashMap<String, String> map = new HashMap<String, String>();
map.put(TAG_ID, id);
map.put(TAG_INTERPRET, interpret);
map.put(TAG_TITEL, titel);
map.put(TAG_ALBUM, album);
map.put(TAG_ALBUMCOVER, albumcover);
map.put(TAG_LIKES, likes);
songslist.add(map);
}
but List is empty. The JSONArray includes the values.
The code that creates the map and puts the elements in the list is ok. So its either
1) songslist is messed up. You don't show where/how its created
2) you think charts has items in it, but it doesn't.
You're not entering into the loop. Your posted code its OK. charts.length() == 0