serialize map of maps to dyanmodb to json - java

To attribute Map below in a class that i want to save and read from Dyanmodb, using DynamoDBMapper.
Map<String, Map<String, Transition>> twf;
public class Transition {
public String fst;
public Permission pm;
public List<Action> ac;
}
public class Action {
private String mdl;
private String dsc;
private String nm;
// email address or any other data
private Map<String, String> data;
}
i have tried DynamoDBTypeConverted to convert to String, that results in json string that has " escaped as \" and unreadable in dyanmodb. I wanted to store as json
I implemented with understanding that Dyanmodb supports Map, but i still get error :
Exception processing message: not supported; requires #DynamoDBTyped or #DynamoDBTypeConverted
public class TimeSheetWorkFlowConverter implements
DynamoDBTypeConverter<Map<String, Object>, Map<String, Map<String, Transition>>> {
#Override
public Map convert(Map<String, Map<String, Transition>> object) {
// Map obj = mapper.readValue(object, Map.class);
String newJson = null;
Map objectJson = null;
try {
newJson = mapper.writeValueAsString(object);
objectJson = mapper.readValue(newJson, Map.class);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return objectJson;
}
#SuppressWarnings("unchecked")
#Override
public Map<String, Map<String, Transition>> unconvert(Map<String, Object> object) {
Map<String, Map<String, Transition>> wf = new HashMap<>();
if (object != null && !object.isEmpty())
for (Entry<String, Object> entry : object.entrySet()) {
String key = entry.getKey();
Map<String, Transition> value = mapTransition(entry.getValue());
wf.put(key, value);
}
return wf;
}

Related

How to traverse all values of LinkedTreeMap<String, Object>?

So, I have JSON file and all data I put to LinkedTreeMap<String, Object>. If one of JSON field is complex:
{
"val1": "1",
"val2": "2",
"val3": {
"embVal1": "emb1",
"embVal2": emb2
},
"val4": "4"
}
like val3, map value with Object type will transform to other LinkedTreeMap<String, Object>, and my structure will look like LinkedTreeMap<String, LinkedTreeMap<Sting, Object>>.
If val3 in it body has other complex object, my value of Object type will also transform to new LinkedTreeMap<String, Object> and so on into the depths of Json tree.
How can I traverse all embedded nodes in structure like this?
I did the code below, I didn't think in performance so much but it works well
AppTest.java
public class AppTest {
#Test
public void testApp() {
LinkedTreeMap<String, Object> node = new LinkedTreeMap<>();
LinkedTreeMap<String, Object> node2 = new LinkedTreeMap<>();
LinkedTreeMap<String, Object> node3 = new LinkedTreeMap<>();
node2.put("embembVal1", "embemb1");
node2.put("embembVal2", "embemb2");
node3.put("embVal1", "emb1");
node3.put("embVal2", node2);
node.put("val1", "1");
node.put("val2", "2");
node.put("val3", node3);
node.put("val4", "4");
MyJson json = new MyJson();
json.read(node);
System.out.println(MyJsonBuilder.build());
}
}
MyJson.java
public class MyJson {
public void read(LinkedTreeMap<String, Object> node) {
MyJsonBuilder.append("{");
for(Entry<String, Object> set : node.entrySet()) {
if(!getInstanceType(set.getValue())) {
jsonFormat(set.getKey(), set.getValue());
} else {
new MyJson().read( (LinkedTreeMap<String, Object>) set.getValue() );
}
}
MyJsonBuilder.append("}");
}
private void jsonFormat(String k, Object v) {
MyJsonBuilder.append( String.format("\"%s\":\"%s\"", k, v) );
}
private boolean getInstanceType(Object obj) {
if(obj instanceof LinkedTreeMap) return true;
else return false;
}
}
MyJsonBuilder.java
public class MyJsonBuilder {
private static StringBuilder jsonBuilder = new StringBuilder();
public static void append(String node) {
jsonBuilder.append(node);
}
private static String format(String json) {
String adjustedjson = json;
if (adjustedjson.contains("\"\"")) adjustedjson = adjustedjson.replaceAll("\"\"", "\",\"");
if (adjustedjson.contains("}\"")) adjustedjson = adjustedjson.replaceAll("}\"", "},\"");
return adjustedjson;
}
public static String build() {
return format(jsonBuilder.toString());
}
}

Java deparam the json object parameterized by Jquery.param() method

Is there a utility in java to de parameterize the object parameterized by Jquery param() method. I got the following code working for now( I can parse the returned map to a Json object). Don't know how robust it will be. Is there a util in java just like js one here
public class Util {
/**
* Deparameterize to original json form the query params coming from the jquery.param() method.
* #param query the query string key value(array of values if same key repeated) pairs.
* #return
*/
public static Map<String, Object> deParam(Map<String, String[]> query) {
Map<String, Object> map = new HashMap<>();
List<Map<String,Object>> toArray=new ArrayList<>();
for (String key : query.keySet()) {
//ex key $and[0][price][$lt]
String value=query.get(key)[0];
key = key.replace("]", "");
String[] split = key.split("\\[");
Map<String, Object> grandParent =null;
Map<String, Object> parent =map;
String parentName="root";
Map<String, Object> child = null;
String lastSkey=null;
for (String skey : split) {
Object me = parent.get(skey);
if(skey.matches("[0-9]+")){
//if array key
toArray.add(parent);
parent.put("parent",grandParent);
parent.put("myName", parentName );
}
if (me == null) {
child=new HashMap<>();
parent.put(skey, child);
grandParent=parent;
parent=child;
parentName=skey;
} else {
grandParent=parent;
parent = (Map<String, Object>) me;
parentName=skey;
}
lastSkey=skey;
}
if(value.matches("[0-9]+\\.?[0-9]+")){
Double numVal=new Double(value);
grandParent.put(lastSkey,numVal);
}else {
grandParent.put(lastSkey,value);
}
}
for (Map<String, Object> arrayMap : toArray) {
Map<String, Object> myParent = (Map<String, Object>) arrayMap.remove("parent");
String myName = (String) arrayMap.remove("myName");
if(myParent!=null&&myName!=null){
myParent.put(myName, arrayMap.values());
}else if(myName!=null && myName.equals("root")){
map.put("list", arrayMap.values());
}
}
return map;
}
}

How to serialize with Jackson a java.util.Map based class

I have a class which looks like this:
#JsonFormat(shape=JsonFormat.Shape.OBJECT)
public class MyMap implements Map<String, String>
{
protected Map<String, String> myMap = new HashMap<String, String>();
protected String myProperty = "my property";
public String getMyProperty()
{
return myProperty;
}
public void setMyProperty(String myProperty)
{
this.myProperty = myProperty;
}
//
// java.util.Map mathods implementations
// ...
}
And a main method with this code:
MyMap map = new MyMap();
map.put("str1", "str2");
ObjectMapper mapper = new ObjectMapper();
mapper.getDeserializationConfig().withAnnotationIntrospector(new JacksonAnnotationIntrospector());
mapper.getSerializationConfig().withAnnotationIntrospector(new JacksonAnnotationIntrospector());
System.out.println(mapper.writeValueAsString(map));
When executing this code I'm getting the following output: {"str1":"str2"}
My question is why the internal property "myProperty" is not serialized with the map?
What should be done to serialize internal properties?
Most probably you will end up with implementing your own serializer which will handle your custom Map type. Please refer to this question for more information.
If you choose to replace inheritance with composition, that is to make your class to include a map field not to extend a map, then it is pretty easy to solve this using the #JsonAnyGetter annotation.
Here is an example:
public class JacksonMap {
public static class Bean {
private final String field;
private final Map<String, Object> map;
public Bean(String field, Map<String, Object> map) {
this.field = field;
this.map = map;
}
public String getField() {
return field;
}
#JsonAnyGetter
public Map<String, Object> getMap() {
return map;
}
}
public static void main(String[] args) throws JsonProcessingException {
Bean map = new Bean("value1", Collections.<String, Object>singletonMap("key1", "value2"));
ObjectMapper mapper = new ObjectMapper();
System.out.println(mapper.writeValueAsString(map));
}
}
Output:
{"field":"value1","key1":"value2"}

Bind multiple elements to map with attribute as key with java XML annotations, JAXB

I have an XML source from which I unmarshall Objects with JAXB.
The XML source:
<album>
<name>something</name>
<id>003030</id>
<artist>someone</artist>
...
</album>
The java source is like (with the required getter/setters as well):
#XmlRootElement(name="album")
class Album {
String name;
Long id;
String artist;
...
}
So far so good. Now I get some image urls in different sizes within album list:
...
<image size="small">http://.../small.jpg</image>
<image size="medium">http://.../medium.jpg</image>
<image size="large">http://.../large.jpg</image>
...
I want to map it to a java Map something like this:
Map<String,String> imageUrls;
Where the map's key would be the size attribute and the map's value would be the element value.
If it's possible, how should I annotate this variable?
helper class Pair
#XmlAccessorType(XmlAccessType.FIELD)
public class Pair {
#XmlAttribute
private String key;
#XmlValue
private String value;
public Pair() {
}
public Pair(String key, String value) {
this.key = key;
this.value = value;
}
//... getters, setters
}
List of pairs
#XmlAccessorType(XmlAccessType.FIELD)
public class PairList
{
private List<Pair> values = new ArrayList<Pair>();
public PairList() {
}
//...
}
adaptor
public class MapAdaptor extends XmlAdapter<PairList, Map<String, String>>
{
#Override
public Map<String, String> unmarshal(PairList list) throws Exception
{
Map<String, String> retVal = new HashMap<String, String>();
for (Pair keyValue : list.getValues())
{
retVal.put(keyValue.getKey(), keyValue.getValue());
}
return retVal;
}
#Override
public PairList marshal(Map<String, String> map) throws Exception
{
PairList retVal = new PairList();
for (String key : map.keySet())
{
retVal.getValues().add(new Pair(key, map.get(key)));
}
return retVal;
}
}
usage in your entity
#XmlJavaTypeAdapter(value = MapAdaptor.class)
private Map<String, String> imageUrls = new HashMap<String, String>();
PS
You can do it without class PairList using Pair[] instead of PairList
adaptor
public class MapAdaptor extends XmlAdapter<Pair[], Map<String, String>>
{
#Override
public Map<String, String> unmarshal(Pair[] list) throws Exception
{
Map<String, String> retVal = new HashMap<String, String>();
for (Pair keyValue : Arrays.asList(list))
{
retVal.put(keyValue.getKey(), keyValue.getValue());
}
return retVal;
}
#Override
public Pair[] marshal(Map<String, String> map) throws Exception
{
List<Pair> retVal = new ArrayList<Pair>();
for (String key : map.keySet())
{
retVal.add(new Pair(key, map.get(key)));
}
return retVal.toArray(new Pair[]{});
}
}
but in this case you can't control name of every pair. It will be item and you can't change it
<item key="key2">valu2</item>
<item key="key1">valu1</item>
PS2
If you will try use List<Pair> instead of PairList, you will get Exception
ERROR: java.util.List haven't no-arg constructor

How do I access nested HashMaps in Java?

I have a HashMap in Java, the contents of which (as you all probably know) can be accessed by
HashMap.get("keyname");
If a have a HashMap inside another HashMap i.e. a nested HashMap, how would i access the contents? Can i do this like this, inline:
HashMap.get("keyname").get("nestedkeyname");
Thank you.
You can do it like you assumed. But your HashMap has to be templated:
Map<String, Map<String, String>> map =
new HashMap<String, Map<String, String>>();
Otherwise you have to do a cast to Map after you retrieve the second map from the first.
Map map = new HashMap();
((Map)map.get( "keyname" )).get( "nestedkeyname" );
You can get the nested value by repeating .get(), but with deeply nested maps you have to do a lot of casting into Map. An easier way is to use a generic method for getting a nested value.
Implementation
public static <T> T getNestedValue(Map map, String... keys) {
Object value = map;
for (String key : keys) {
value = ((Map) value).get(key);
}
return (T) value;
}
Usage
// Map contents with string and even a list:
{
"data": {
"vehicles": {
"list": [
{
"registration": {
"owner": {
"id": "3643619"
}
}
}
]
}
}
}
List<Map> list = getNestedValue(mapContents, "data", "vehicles", "list");
Map first = list.get(0);
String id = getNestedValue(first, "registration", "owner", "id");
Yes.
See:
public static void main(String args[]) {
HashMap<String, HashMap<String, Object>> map = new HashMap<String, HashMap<String,Object>>();
map.put("key", new HashMap<String, Object>());
map.get("key").put("key2", "val2");
System.out.println(map.get("key").get("key2"));
}
If you plan on constructing HashMaps with variable depth, use a recursive data structure.
Below is an implementation providing a sample interface:
class NestedMap<K, V> {
private final HashMap<K, NestedMap> child;
private V value;
public NestedMap() {
child = new HashMap<>();
value = null;
}
public boolean hasChild(K k) {
return this.child.containsKey(k);
}
public NestedMap<K, V> getChild(K k) {
return this.child.get(k);
}
public void makeChild(K k) {
this.child.put(k, new NestedMap());
}
public V getValue() {
return value;
}
public void setValue(V v) {
value = v;
}
}
and example usage:
class NestedMapIllustration {
public static void main(String[] args) {
NestedMap<Character, String> m = new NestedMap<>();
m.makeChild('f');
m.getChild('f').makeChild('o');
m.getChild('f').getChild('o').makeChild('o');
m.getChild('f').getChild('o').getChild('o').setValue("bar");
System.out.println(
"nested element at 'f' -> 'o' -> 'o' is " +
m.getChild('f').getChild('o').getChild('o').getValue());
}
}
As others have said you can do this but you should define the map with generics like so:
Map<String, Map<String, String>> map = new HashMap<String, Map<String,String>>();
However, if you just blindly run the following:
map.get("keyname").get("nestedkeyname");
you will get a null pointer exception whenever keyname is not in the map and your program will crash. You really should add the following check:
String valueFromMap = null;
if(map.containsKey("keyname")){
valueFromMap = map.get("keyname").get("nestedkeyname");
}
Yes, if you use the proper generic type signature for the outer hashmap.
HashMap<String, HashMap<String, Foo>> hm = new HashMap<String, HashMap<String, Foobar>>();
// populate the map
hm.get("keyname").get("nestedkeyname");
If you're not using generics, you'd have to do a cast to convert the object retrieved from the outer hash map to a HashMap (or at least a Map) before you could call its get() method. But you should be using generics ;-)
I prefer creating a custom map that extends HashMap. Then just override get() to add extra logic so that if the map doesnt contain your key. It will a create a new instance of the nested map, add it, then return it.
public class KMap<K, V> extends HashMap<K, V> {
public KMap() {
super();
}
#Override
public V get(Object key) {
if (this.containsKey(key)) {
return super.get(key);
} else {
Map<K, V> value = new KMap<K, V>();
super.put((K)key, (V)value);
return (V)value;
}
}
}
Now you can use it like so:
Map<Integer, Map<Integer, Map<String, Object>>> nestedMap = new KMap<Integer, Map<Integer, Map<String, Object>>>();
Map<String, Object> map = (Map<String, Object>) nestedMap.get(1).get(2);
Object obj= new Object();
map.put(someKey, obj);
I came to this StackOverflow page looking for a something ala valueForKeyPath known from objc. I also came by another post - "Key-Value Coding" for Java, but ended up writing my own.
I'm still looking for at better solution than PropertyUtils.getProperty in apache's beanutils library.
Usage
Map<String, Object> json = ...
public String getOptionalFirstName() {
return MyCode.getString(json, "contact", "firstName");
}
Implementation
public static String getString(Object object, String key0, String key1) {
if (key0 == null) {
return null;
}
if (key1 == null) {
return null;
}
if (object instanceof Map == false) {
return null;
}
#SuppressWarnings("unchecked")
Map<Object, Object> map = (Map<Object, Object>)object;
Object object1 = map.get(key0);
if (object1 instanceof Map == false) {
return null;
}
#SuppressWarnings("unchecked")
Map<Object, Object> map1 = (Map<Object, Object>)object1;
Object valueObject = map1.get(key1);
if (valueObject instanceof String == false) {
return null;
}
return (String)valueObject;
}
import java.util.*;
public class MyFirstJava {
public static void main(String[] args)
{
Animal dog = new Animal();
dog.Info("Dog","Breezi","Lab","Chicken liver");
dog.Getname();
Animal dog2= new Animal();
dog2.Info("Dog", "pumpkin", "POM", "Pedigree");
dog2.Getname();
HashMap<String, HashMap<String, Object>> dogs = new HashMap<>();
dogs.put("dog1", new HashMap<>() {{put("Name",dog.name);
put("Food",dog.food);put("Age",3);}});
dogs.put("dog2", new HashMap<>() {{put("Name",dog2.name);
put("Food",dog2.food);put("Age",6);}});
//dogs.get("dog1");
System.out.print(dogs + "\n");
System.out.print(dogs.get("dog1").get("Age"));
}
}
Example Map:
{
"data": {
"userData": {
"location": {
"city": "Banja Luka"
}
}
}
}
Implementation:
public static Object getValueFromMap(final Map<String, Object> map, final String key) {
try {
final String[] tmpKeys = key.split("\\.");
Map<String, Object> currentMap = map;
for (int i = 0; i < tmpKeys.length - 1; i++) {
currentMap = (Map<String, Object>) currentMap.get(tmpKeys[i]);
}
return currentMap.get(tmpKeys[tmpKeys.length - 1]);
} catch (Exception exception) {
return null;
}
}
Usage:
final Map<String, Object> data = new HashMap<>();
final Map<String, Object> userData = new HashMap<>();
final Map<String, Object> location = new HashMap<>();
location.put("city", "Banja Luka");
userData.put("location", location);
data.put("userData", userData);
System.out.println(getValueFromMap(data, "userData.location.city"));
Result:
Banja Luka
Process finished with exit code 0
I hit this discussion while trying to figure out how to get a value from a nested map of unknown depth and it helped me come up with the following solution to my problem. It is overkill for the original question but maybe it will be helpful to someone that finds themselves in a situation where you have less knowledge about the map being searched.
private static Object pullNestedVal(
Map<Object, Object> vmap,
Object ... keys) {
if ((keys.length == 0) || (vmap.size() == 0)) {
return null;
} else if (keys.length == 1) {
return vmap.get(keys[0]);
}
Object stageObj = vmap.get(keys[0]);
if (stageObj instanceof Map) {
Map<Object, Object> smap = (Map<Object, Object>) stageObj;
Object[] skeys = Arrays.copyOfRange(keys, 1, keys.length);
return pullNestedVal(smap, skeys);
} else {
return null;
}
}

Categories

Resources