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.
Related
This is my Saving Program Code this will save the score, date and the player name to the leaderboard:
mLeaderboardlist = new ArrayList<>();
Leaderboardmodel s = new Leaderboardmodel();
s.setDate("07/24/17");
s.setName(player.getText().toString());
s.setScore(Integer.parseInt(String.valueOf(yourScore.getText())));
Tab1Normal.mLeaderboardlist.add(s);
SharedPreferences appSharedPrefs = PreferenceManager
.getDefaultSharedPreferences(getApplicationContext());
SharedPreferences.Editor prefsEditor = appSharedPrefs.edit();
Gson gson = new Gson();
String json = gson.toJson(s);
prefsEditor.putString("MyObject", json);
prefsEditor.apply();
prefsEditor.commit();
And this is my retrieving program code of dealing also in sharedpreference:
SharedPreferences appSharedPrefs = PreferenceManager
.getDefaultSharedPreferences(this.getActivity().getApplicationContext());
Gson gson = new Gson();
String json = appSharedPrefs.getString("MyObject", "");
Type type = new TypeToken<ArrayList<Leaderboardmodel>>(){}.getType();
ArrayList<Leaderboardmodel> leaderboard= gson.fromJson(json, type);
Collections.sort(leaderboard);
adapter = new ListLeaderBoardAdapter(getActivity(), leaderboard);
lvLeaderboardlist.setAdapter(adapter);
The save saving part work fines but the retrieving part display an error and makes the application crash, the error display :
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $
The problem is that you put an object, not a json.
Leaderboardmodel s = new Leaderboardmodel();
....
String json = gson.toJson(s);
prefsEditor.putString("MyObject", json);
You need to put your array
mLeaderboardlist = new ArrayList<>();
...
String json = gson.toJson(mLeaderboardlist );
Try to debug into your loaded json and see if you really get valid json String.
There is also already a similar question on so: Parsing generic ArrayList using GSON
When you are saving you are saving object not arraylist,
String json = gson.toJson(s);
here s is object of Leaderboardmodel and not arraylist of Leaderboardmodel
So when you retrieve, retrieve it as object not array list like,
Type type = new TypeToken<Leaderboardmodel>(){}.getType();
Leaderboardmodel leaderboard= gson.fromJson(json, type);
Change this line
ArrayList<Leaderboardmodel> leaderboard= gson.fromJson(json, type);
to this
Leaderboardmodel[] leaderboard= gson.fromJson(json, Leaderboardmodel[].class);
and see if it works.
I hope so.
Update:
You need to create an array list of Leaderboardmodel , then call sort.
ArrayList<Leaderboardmodel > leaderboardmodels = new ArrayList<>();
leaderboardmodels.addAll(leaderboard);
Collections.sort(leaderboardmodels);
I want to save Hashset Object in to Sharedpreference and than want retrieve that data. I am storing data in to hashset and and converting object in to json using Gson. Actually m storing bitmap in to Hashset. I am able to convert and save Hashsetobject into sharedpreference. I am getting problem when I am retrieving and converting json to Hashset Object.
HashSet<images> img = new HashSet<images>(CIRCLES_LIMIT);
Here is Method For Saving Object in to Sharedpreference.
public void saveString() throws JSONException {
Object spSquare = c.getStringDrawObjImages();
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(getContext());
SharedPreferences.Editor editor = sharedPrefs.edit();
Gson gson = new Gson();
String jsonSquare = gson.toJson(spSquare)
editor.putString("kEySquare", jsonSquare);
editor.commit();
}
Method For Retrieving That Object.
public void openString() {
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(getContext());
Gson gson = new Gson();
String jsonSquare=sharedPrefs.getString("kEySquare",null);
Type typeSquare = new TypeToken<HashSet<images>>(){}.getType();
HashSet<images> arrayListSquare = gson.fromJson(jsonSquare,typeSquare);`//getting Exception here jsonSyntax Error`
if (arrayListSquare != null) {
img = arrayListSquare;
}
}
As per your comment your json as follows is not in format so that Gson can parse it as you are receiving your circle attribute in string not as json.
{
"img": "[Circle[218.69626, 475.58936, 0,android.graphics.Bitmap#42e13c70,0.0,0.0,0.0,0.0,0.0,0.0,], Circle[186.74065, 670.43713, 0,android.graphics.Bitmap#42e13c70,0.0,0.0,0.0,0.0,0.0,0.0,]]"
}
So your Json is received as object having only attribute that is img.
and you are parsing it as array. That's error. So contact your back end developer and change json structure accordingly.
You serialise a object and want to deserialise it into a HashSet. That's the problem.
Object spSquare = c.getStringDrawObjImages();
What's the type of spSquare? Suppose it is 'Foo.class', you should deserialise it like this:
Foo foo = gson.fromJson(jsonString, Foo.class);
'foo.img' should be your HashSet
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.
We have a requirement to update the JSON data in middle and need to return the updated JSON data using java. Also it should support any type of JSON data.
ex:
Assume {object:{"color":"red","shape":"Triangle"}} is the JSON data and in this we need to update the shape value to Rectangle and we need to return the updated JSON data as below:
{object:{"color":"red","shape":"Rectangle"}}
For this we need to pass the element path ( which element we need to update) and updateText and JSON Data to the JAVA code.
here is the methodCall:
updateValue("object/shape", "Rectangle", "{object:{"color":"red","shape":"Triangle"}}")
We tried below code using Gson library. But with this code we are able to update the targeted Json element, but the requirement is to return the entire JSON data with the updated value.
So please suggest how do we re-build the JSON data with the updated text.
Below is the code we tried to update the Json Data.
public String updateValue(String keyPath, String updateText, String jsonText) {
String[] keys = keyPath.split("/");
JsonParser jsonParser = new JsonParser();
JsonObject jsonObject = (JsonObject) jsonParser.parse(jsonText);
String result = "";
for(String key : keys)
{
if (jsonObject.get(key) instanceof JsonObject)
{
jsonObject = (JsonObject)jsonObject.get(key);
}
else if(jsonObject.get(key) instanceof JsonArray)
{
JsonArray jsonArray = (JsonArray)jsonObject.get(key);
result = jsonArray.toString();
}
else
{
result = jsonObject.get(key).toString();
}
}
result = result.replace(result, updateText);
return result;
}
The problem lies in the way you do the replacements. When you translate the JsonObject to String, you lose the object, and after replacement, you just have the replaced String. To fix it, you need to operate directly on the object, instead of the String counterpart. Because JsonObject is mutable, holding a reference to the input will reflect the changes. One drawback is you can't replace a value in a JsonArray this way, partly because you don't know which element to replace. To accomplish that, you will need a little more in the input(either the value to replace or the element position).
public String updateValue(String keyPath, String updateText, String jsonText) {
String[] keys = keyPath.split("/");
JsonParser jsonParser = new JsonParser();
JsonObject jsonObject = (JsonObject) jsonParser.parse(jsonText);
JsonObject returnVal = jsonObject; // This holds the ref to target json object
JsonPrimitive jp = new JsonPrimitive(updateText);
String finalKey = keys[keys.length - 1];
for(String key : keys)
{
if (jsonObject.get(key).isJsonObject())
{
jsonObject = (JsonObject)jsonObject.get(key);
}
}
jsonObject.remove(finalKey);
jsonObject.add(finalKey, jp);
return returnVal.toString();
}
You can use JsonPath lib for that and try using the following code.
private static final Configuration configuration = Configuration.builder()
.jsonProvider(new JacksonJsonNodeJsonProvider())
.mappingProvider(new JacksonMappingProvider())
.build();
JsonNode updatedJson = JsonPath.using(configuration).parse(originaljson)
.set("use the path to go for value", "new value").json();
json = updatedJson.toString();
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();
}