How can I write and read ListMultimap to file using Properties?
I have an index as follows:
ListMultimap<Object, Object> index = ArrayListMultimap.create();
and writing index to file using Properties as follows:
writeIndexToFile(ListMultimap<Object, Object> listMultimap, String fileName) {
Properties properties = new Properties();
properties = MapUtils.toProperties(toMap(listMultimap));
properties.store(new FileOutputStream(fileName),null);
}
where, toMap() method is:
Map<Object, Object> toMap(ListMultimap<Object, Object> multiMap) {
if (multiMap == null) {
return null;
}
Map<Object, Object> map = new HashMap<Object, Object>();
for (Object key : multiMap.keySet()) {
map.put(key, multiMap.get(key));
}
return map;
}
After running this code, I found the output file is empty. Why nothing is getting written into file?
in above code I cannot call directly as:
MapUtils.toProperties(listMultimap);
because listMultimap is not of type Map. So I converted it to Map using method toMap(). But still it seems that Properties is unable to get map correctly.
Note:
I tried printing listMultimap by converting it to JSON using Gson, but this also failed to convert to string. No Exception occured, but it returned empty string. Actual listMultimap is something like:
where, index == listMultimap.
I'm not getting where am I going wrong.
Related
I have a requirement wherein I need to iterate over a List of Maps i.e. List<Map<String, Object>> grab the data from the list, and map it to a JSON file. Now the challenge is that I need to loop the data dynamically in the JSON file. Well, I do know how to map a single set of data to a JSON file using Thymeleaf but I'm not sure how to dynamically loop a JSON file using Thymeleaf.
The following thing is what I'm aware of -
I have a java class with a method that has the following code that will map the data from a HashMap to the JSON file.
public JSONObject response(){
Map<String, Object> map = new HashMap<>();
Context context = new Context();
String responsePayload = null;
JSONObject jsonObject = null;
data.put("name", "Wayne Rooney")
data.put("profession", "Footballer")
context.setVariable("data", data);
responsePayload = templateEngine.process("resource/payload", context);
jsonObject = new JSONObject(responsePayload);
}
This is how the payload.json file looks
{
"name": "[(${data['name']})]",
"profession": "[(${data['profession']})]"
}
So, my code works smoothly when only a single instance of HashMap data is mapped to the JSON file, but my next requirement is how do I loop a List of Maps i.e. List<Map<String, Object>> and map the data in my json file?
For e.g. Consider now I've a List<Map<String, Object>> instead of Map<String, Object>
public JSONObject response(){
List<Map<String, Object>> listOfMap = new ArrayList<>();
Map<String, Object> data1 = new HashMap<>();
Map<String, Object> data2 = new HashMap<>();
Map<String, Object> data3 = new HashMap<>();
Context context = new Context();
String responsePayload = null;
JSONObject jsonObject = null;
data1.put("name", "Wayne Rooney")
data1.put("profession", "Footballer")
data2.put("name", "Cristiano Ronaldo")
data2.put("profession", "Footballer")
data3.put("name", "Sir Alex Ferguson")
data3.put("profession", "Manager")
listOfMap.add(data1);
listOfMap.add(data2);
listOfMap.add(data3);
context.setVariable("data", listOfMap);
responsePayload = templateEngine.process("resource/payload", context);
jsonObject = new JSONObject(responsePayload);
return jsonObject;
}
So now how do I map this list of data to a JSON file? What changes do I need to make in the JSON file?
I appreciate it if someone helps here.
Thank you!
Consider the following code:
public void testDumpWriter() {
Map<String, Object> data = new HashMap<String, Object>();
data.put("NAME1", "Raj");
data.put("NAME2", "Kumar");
Yaml yaml = new Yaml();
FileWriter writer = new FileWriter("/path/to/file.yaml");
for (Map.Entry m : data.entrySet()) {
String temp = new StringBuilder().append(m.getKey()).append(": ").append(m.getValue()).toString();
yaml.dump(temp, file);
}
}
The output of the above code is
'NAME1: Raj'
'NAME2: Kumar'
But i want the output without the single quotes like
NAME1: Raj
NAME2: Kumar
This thing is very comfortable for parsing the file.
If anyone have solution, please help me to fix. Thanks in advance
Well SnakeYaml does exactly what you tell it to: For each entry in the Map, it dumps the concatenation of the key, the String ": ", and the value as YAML document. A String maps to a Scalar in YAML, and since the scalar contains a : followed by space, it must be quoted (else it would be a key-value pair).
What you actually want to do is to dump the Map as YAML mapping. You can do it like this:
public void testDumpWriter() {
Map<String, Object> data = new HashMap<String, Object>();
data.put("NAME1", "Raj");
data.put("NAME2", "Kumar");
DumperOptions options = new DumperOptions();
options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
Yaml yaml = new Yaml(options);
FileWriter writer = new FileWriter("/path/to/file.yaml");
yaml.dump(data, writer);
}
I have the Yaml file:
#Define CDN domains
---
CDN:
quality: 200..300
cost: low
Video-type: mp4
and with this Java code, I retrieve sub values of CDN:
// The path of your YAML file.
Yaml yaml = new Yaml();
Map<String, Map<String, String>> values =
(Map<String, Map<String, String>>) yaml
.load(new FileInputStream(new File("/workspace/servlet-yaml/src/test.yaml")));
for (String key : values.keySet()) {
Map<String, String> subValues = values.get(key);
for (String subValueKey : subValues.keySet()) {
System.out.println(values);
}
}
The output is:
{CDN={quality=200..300, cost=low, Video-type=mp4}}
{CDN={quality=200..300, cost=low, Video-type=mp4}}
{CDN={quality=200..300, cost=low, Video-type=mp4}}
First of all, I don't know why it repeats three times?
Secondly, I want to write a code that
if cost = low , then do somthing.
First of all, I dont know whay it reapets three times?
Because you tell it to. For each subValueKey, print the whole value set. There are three sub-keys, so the complete value set gets printed three times.
Secondly, I want to write a code that if cost = low , then do somthing.
Yaml yaml = new Yaml();
Map<String, Map<String, String>> values =
(Map<String, Map<String, String>>) yaml.load(
new FileInputStream(new File(
"/workspace/servlet-yaml/src/test.yaml")));
final Map<String, String> cdn = values.get("CDN");
// or iterate over all keys like you currently do
final String cost = cdn.get("cost");
// or iterate over all subkeys and compare them to "cost".
// that way, it's easier to handle missing keys.
if ("low".equals(cost)) {
// do something
}
I've got a YAML file that looks like this:
---
name:
storage:
documentfiles:
username: rafa
password: hello
And I'm trying to get the last two username and password values. My current code is the one below. I'm using a Map to store the YAML values, but since there is more than one child when I map.get() anything past name it gives me a null value. if I do map.get(name) I get {storage={documentfiles={username=rafa, password=hello}}} Does anyone know how I can correctly get the username and password?
public Map grabYaml(){
Yaml reader = new Yaml();
InputStream inputStream = getClass().getClassLoader().getResourceAsStream(yamlFileName);
Map map = (Map) reader.load(inputStream);
return map;
}
Something like this
public class Test {
public Map grabYaml() throws IOException {
Yaml reader = new Yaml();
InputStream inputStream = new FileInputStream(new File(yamlFileName));
Map map = (Map) reader.load(inputStream);
return map;
}
public static void main(String[] args) throws IOException {
Map storage = (Map) new Test().grabYaml().get("name");
Map documentfiles = (Map)storage.get("storage");
Map userData = (Map) documentfiles.get("documentfiles");
System.out.println(userData.get("username"));
System.out.println(userData.get("password"));
}
}
I tried writing ListMultimap to file using Properties, but it seems impossible, refer to question Writing and reading ListMultimap to file using Properties.
Going ahead, if using Properties to store ListMultimap is not correct way, how can we store ListMultimap into a file? And how can we read back from file?
e.g. lets say I have:
ListMultimap<Object, Object> index = ArrayListMultimap.create();
How can I write methods to write this ListMultimap to file and read back from file:
writeToFile(ListMultimap multiMap, String filePath){
//??
}
ListMultimap readFromFile(String filePath){
ListMultimap multiMap;
//multiMap = read from file
return multiMap;
}
You need to decide how you will represent each object in the file. For example, if your ListMultimap contained Strings you could simply write the string value but if you're dealing with complex objects you need to produce a representation of those object as a byte[], which if you want to use Properties should then be Base64 encoded.
The basic read method should be something like:
public ListMultimap<Object, Object> read(InputStream in) throws IOException
{
ListMultimap<Object, Object> index = ArrayListMultimap.create();
Properties properties = new Properties();
properties.load(in);
for (Object serializedKey : properties.keySet())
{
String deserializedKey = deserialize(serializedKey);
String values = properties.get(serializedKey);
for (String value : values.split(","))
{
index.put(deserializedKey, deserialize(value));
}
}
return index;
}
And the write method this:
public void write(ListMultimap<Object, Object> index, OutputStream out) throws IOException
{
Properties properties = new Properties();
for (Object key : index.keySet())
{
StringBuilder values = new StringBuilder();
for (Object value = index.get(key))
{
values.append(serailize(value)).append(",");
}
properties.setProperty(serailize(key), values.subString(0, values.length - 1));
}
properties.store(out, "saving");
}
This example makes use of serialize and deserialize methods that you'll need to define according to your requirements but the signatures are:
public String serialize(Object object)
and
public Object deserialize(String s)