How can I can save HashMap in my Android app? - java

I have member variable HashMap<Integer, HashMap<String[], Integer>> in some activity in my Android app. The HashMap supposed to survive from user launch app for the first time till the app will be deleted. I can't use shared preferences because there aren't such put method. I know about room database but I don't really want to use that in this case. Please, tell me which options are there to save HashMap and store it in memory.

You can try to serialize HashMap to string.
Import this library in your build.gradle file first.
implementation 'com.google.code.gson:gson:2.8.6'
To have serialize data you can follow this code:
public static String hashToString (HashMap<Integer, HashMap<String[], Integer>> hashMap) {
if (hashMap == null) return null;
Gson gson = new Gson();
//import java.lang.reflect.Type;
//import com.google.gson.reflect.TypeToken;
Type type = new TypeToken<HashMap<Integer, HashMap<String[], Integer>>(){}.getType();
return gson.toJson(hashMap, type);
}
Now you can convert any object to string you can use this method..
To get back object from string:
public static HashMap<Integer, HashMap<String[], Integer>> stringToHash (String json) {
if (json == null) return null;
Gson gson = new Gson();
//import java.lang.reflect.Type;
//import com.google.gson.reflect.TypeToken;
Type type = new TypeToken<HashMap<Integer, HashMap<String[], Integer>>(){}.getType();
return gson.fromJson(json, type);
}

PaperDB library is best for store anything believe i use paperDB to store HashMap,POJO Class Object, Array and so on... and it just serializes the any object store in local storage.
Github Link Of PaperDB : https://github.com/pilgr/Paper
In Above Link you can learn about how to use this!

Related

How to read multiple values from the json object in java

I want to read the values which is there in json object
example :
remote":{"ip":"127.0.0.1","port":35637}
How can I convert this ip and port into string in java?
Here's how to use the Google Gson library to extract the two scalar values from your structure:
import com.google.gson.Gson;
import java.util.Map;
class Scratch {
public static void main(String[] args) {
// Input data structure - note the added curly braces to make the input
// a valid JSON dictionary and the messy escaping of double quotes. You
// will usually read JSON from a file or have it come in from an API call,
// so escaping like this doesn't come up a lot.
String json = "{\"remote\":{\"ip\":\"127.0.0.1\",\"port\":35637}}";
// Create an instance of the Gson encoder/decoder
Gson gson = new Gson();
// Decode the JSON to a Java data structure
Map<String, Map<String, Object>> map = gson.fromJson(json, Map.class);
// Extract the "remote" key to get the inner dictionary
Map<String, Object> remote = map.get("remote");
// Grab the two inner values. Numbers in JSON are doubles in Java
String ip = (String)remote.get("ip");
double port = (double)remote.get("port");
System.out.println(ip);
System.out.println((int)port);
}
}
Result:
127.0.0.1
35637

Gson: how to include partly serialized object?

Given the class:
class Container<T> {
T item;
String type;
Map<String,String> properties;
public void setItem(T _item) {
item = _item;
}
}
I have already the item serialized in a database as string with the name serialized. It is a Map<String,String>.
I don't know how to say Gson that this variable is already serialized.
So when I use Gson I first deserialize it, then serialize it back
Container<Map <String, String>> t = new Container<>(<other parameters>);
Map <String, String> m = gson.fromJson(serialized, new TypeToken<Map<String,String>>(){}.getType())
t.setItem(m);
gson.toJson(t, new TypeToken<Container<Map<String,String>>>() {}.getType());
This feels inefficient. How do I fix this?
I'm not sure that's possible. You're mixing object creation and serialization.
What you can do is create a new constructor with an additional String parameter and deserialize the string to get your item and set it automatically. That should be possible even with a parameterized type. That way you have 2 lines of code instead of 4.

#sinfonier BOLT - Adding a jarray object to output

If I make
JSONArray array = new JSONArray();
[...]
this.addField("array", array);
it generates:
{..., "array":"[\"x\", \"y\"]" }
When it should be:
{..., "array": ["x", "y"] }
The sinfonier probably calls toString on the jarray object. I think it should create a full json and then call toString on the full json.
Is there any other way to do this?
(this is a sinfonier specific question, sorry, but no sinfonier tag available yet)
So, I participate in sinfonier Hackathon on Campus Party Recife, if you need create a array you need create json objects before and add them in array, like this:
import org.json.JSONArray;
...
List aryLst = new ArrayList();
aryLst.add("x");
aryLst.add("y");
JSONArray list = new JSONArray(aryLst);
Sinfonier use org.json package to manipulate json objects.
But if your bolt gets json from a truple and you save a value of a json in a field you can get this value directly from truple and save. Or you can use json fields normaly like a field in other bolt or drain.
In order to create an array list and add it into a field to your current tuple/map it's necessary to make an ArrayList> instance.
Firts import com.google.gson libraries:
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
Then add every item from your source array to new ArrayList instance:
JSONArray originalJsonArray = new JSONArray(json);
ArrayList<Map<String, Object>> newArrayList = new ArrayList<Map<String, Object>>();
if (originalJsonArray != null) {
for (int i=0;i<originalJsonArray.length();i++){
Map<String, Object> fieldValueItem = new Gson().fromJson(originalJsonArray.get(i).toString(), new TypeToken<HashMap<String, Object>>() {}.getType());
newArrayList.add(fieldValueItem);
}
}
Finally add your new array:
this.addField("newarraylist",newArrayList);
this.addField("newarraylistlength",newArrayList.length());

Create merged JSON with GSON

I've found tons of examples of using GSON to convert either an single object, or a list of that single object, to its respective JSON. Quite easy to do. Even if the object has objects as its properties, this still is trivial.
But let's say I have 5 objects of interest (names, companies, colors, numbers, candy) and they have no relationship to each other at all. So I make my database calls, and now have 5 lists full of all of the above in my code.
Now, how could I put these lists into a JSON Array whose parent name is "items" and contains all of the above as children beneath it? So one parent "items", with 5 children (each child is a sibling of each other).
What is the appropriate way using GSON (or not??) to construct such a tree or structure?
I noticed there is a lot in GSON such as JSONArray and such, but wasn't able to figure it out.
Thanks so much!
Yes, you can. You have to build your own serializer first. For instance:
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
public static String toJson(List<Item> items){
try{
JSONObject jsonObj = new JSONObject();
JSONArray jsonArr = new JSONArray();
for(Item i : items){
JSONObject itemObj = new JSONObject();
itemObj.put("names", i.getName());
itemObj.put("companies", i.getCompanies());
itemObj.put("colors", i.getColors());
itemObj.put("numbers", i.getNumbers());
itemObj.put("candy", i.getCandy());
jsonArr.put(itemObj);
}
jsonObj.put("items", jsonArr);
return jsonObj.toString();
} catch(JSONException ex){
ex.printStackTrace();
}
return null;
}
Depending on what the fields are, you can make a model class and set the objects from database. The use Gson and form your Json string using jsonFrom.
Eg.
public class Items{
ArrayList<String> names;
String candy;
//nested custom class if necessary
ArrayList<Companies> companies;
//other fields here
//getter setter
}
Now set the values for objects of Items.
Then:
Gson gson = new Gson();
String json = gson.toJson(modelClassObject);
If i got your requirement right, json is the String you need.
To merge JSONs you need to define some conventions of merging. If "Overlay" strategy (replace or add) conforms you, you can find a helpful JSON Merging Library in this answer.

Deserialize JSON object that has a map using Gson

I've searched the web for a solution, but, the answers I found only help when the JSON file being parsed is solely a map.
I was wondering if there is a way to parse an object that has an HashMap along with other data.
For example:
public class Data
{
String aName;
HashMap<String, Object> objects;
List<String> aExpressions;
}
I can parse the name and expressions but I don't know how to parse the entire JSON object as a whole.
I think it has something to do with type tokens, but that only works if the whole object is a HashMap.
The presence of HashMap in your class does not change how Gson converts it to and from json.
data d = new data();
//set some values
String json = new Gson().toJson(d);
data d2 = new Gson().fromJson( json, data.class);
That's pretty much it.
Since
JSON can represent four primitive types (strings, numbers,
booleans, and null) and two structured types (objects and arrays).
A string is a sequence of zero or more Unicode characters
[UNICODE].
An object is an unordered collection of zero or more name/value
pairs, where a name is a string and a value is a string, number,
boolean, null, object, or array.
An array is an ordered sequence of zero or more values.
Gson acts 2 ways:
you can let Gson deserialize creating a combination of maps, lists and primitives or
you can specify exactly the kind of object you want, and through reflection, it will fill the desidered fields.
You can mix these two approaches and of course you can do a lot more to solve all your parsing cases (like using custom type adapters).
I prepared you a little example using your class that shows how Gson can parse your data using a combination of maps/list/primitives or passing your class (that has a mixed approach).
package stackoverflow.questions;
import java.util.*;
import com.google.gson.Gson;
public class Q20154323 {
public static class Data {
public String aName;
public HashMap<String, Object> objects;
public List<String> aExpressions;
#Override
public String toString() {
return "Data [aName=" + aName + ", objects=" + objects + ", aExpressions=" + aExpressions + "]";
}
}
public static void main(String[] args) {
Data d = new Data();
d.aName = "Test";
d.objects = new HashMap<>();
d.aExpressions = new ArrayList<>();
d.objects.put("key1", 1L);
d.objects.put("key2", new Date());
d.aExpressions.add("Stack");
d.aExpressions.add("Overflow");
Gson g = new Gson();
String json = g.toJson(d);
System.out.println("As JSON: " +json);
Data d2 = g.fromJson(json, Data.class);
System.out.println("As \"casted\" data type: " + d2);
Object o3 = g.fromJson(json, Object.class);
System.out.println("As \"free\" object: " + o3);
}
}
and this is the execution. It shows you two way of parsing the JSON string that I created using your initial class.
As JSON: {"aName":"Test","objects":{"key2":"Nov 23, 2013 1:33:23 AM","key1":1},"aExpressions":["Stack","Overflow"]}
As "casted" data type: Data [aName=Test, objects={key2=Nov 23, 2013 1:33:23 AM, key1=1.0}, aExpressions=[Stack, Overflow]]
As "free" object: {aName=Test, objects={key2=Nov 23, 2013 1:33:23 AM, key1=1.0}, aExpressions=[Stack, Overflow]}
You can use one or other approach as your needs.
About the TypeToken, due to generics erasure, something like this
List<Data> list = new Gson().parse(aJsonString, List<Data>.class)
won't work, you have to do something like
Type listType = new TypeToken<List<Data>>() {}.getType();
List<Data> list = new Gson().parse(aJsonString, listType.class)
but this case applies, pratically, when your JSON is an array and you want to deserialize it into a list of custom classes.

Categories

Resources