In messagepack, error while getting value from MapValue.. Please help me - java

I'm trying to serialize map using messagpack.write(map). During deserialization using messagepack.read(byte[]) i got MapValue. But I cannot fetch the values using MapValue.get(key). Look this problem below
HashMap<Object,Object> map = new HashMap<Object, Object>();
map.put(1,"ONE");
map.put("ONE","TWO");
MessagePack m= new MessagePack();
byte[] b = m.write(map);
MessagePack m1 = new MessagePack();
MapValue value = (MapValue)m1.read(b);
System.out.println(value);// here I am getting {1:"ONE",2:"TWO"}
System.out.println( value.get(1)); // printing the value for key 1. I am getting null.
Please help on this.. Thanking you.
Nausadh

You need to use ValueFactory and convert key to use a Value interface. It's not really intuitive
// instead of value.get(1) use following
System.out.println(value.get(ValueFactory.createIntegerValue(1)));
// if the key would be a String use:
System.out.println(value.get(ValueFactory.createRawValue("key")));

Related

Cannot convert a linked hash map to a json object with jackson when talking to the Nationbuidler API

My goal is to update a contact in a nationbuilder nation. Nationbuilder is a SAAS for managing campaigns. a "nation" is simply a list of contacts. The endpoint for updating a contact accepts a JSON object in the request body. The object has the form
{ "person": {"first_name": "Bob", "last_name": "Smith", .....many many other fields} }
In my Java code , I have the contact's information available as a Map - a LinkedHashMap type to be exact. I need to convert this to the above JSON object format before I can pass the contact into the Nationbuilder API endpoint. I have tried several approaches and none seem to work. They all result in a 404 Not Found error. Our project uses Jackson - specifically, the javax.ws.rs.client package.
Here is the code that I began with...
LinkedHashMap payload = new LinkedHashMap();
LinkedHashMap person = new LinkedHashMap();
person.put("first_name", "Bob");
person.put("last_name", "SmithFoo");
payload.put("person", person);
LinkedHashMap response = client.post(payload, LinkedHashMap.class);
I also tried converting the payload to a string like this ...
LinkedHashMap payload = new LinkedHashMap();
LinkedHashMap person = new LinkedHashMap();
person.put("first_name", "Bob");
person.put("last_name", "SmithFoo");
payload.put("person", person);
String payloadAsString = Util.getMapper().writeValueAsString(payload);
LinkedHashMap response = client.post(payloadAsString, LinkedHashMap.class);
This also did not work. Interestingly, the value payloadAsString has the exact format I need to pass into the NationBuilder API. However, I think the reason this does not work is because the resulting value is a string rather than a JSON object.
As a third approach, I tried to then convert the string into a json object like this
// Object payloadAsObject = Util.getMapper().convertValue(payload, Object.class);
which just ended up making me realize this was a silly idea because I just ended up with the same linkedhashmap that I began with.
One other approach I tried was creating a payload class. We don't want to create a class for the person object because it would be difficult to maintain an object with 50 or so attributes given the Nationbuilder API will change so the person data needs to be in a map. However, I figured that even though the person attribute needs to be a map, maybe the request will be successful if the payload is an object like this...
public static class Payload{
public Object person;
}
Payload payload = new Payload();
LinkedHashMap person = new LinkedHashMap();
person.put("first_name", "Bob");
person.put("last_name", "SmithFoo");
payload.person = person;
LinkedHashMap response = client.post(payload, LinkedHashMap.class);
This too did not work. (404 not found)
I tested with a very basic POJO and realized my mistake was simply that the endpoint is a PUT rather than a POST. This works just fine....
LinkedHashMap payload = new LinkedHashMap();
LinkedHashMap person = new LinkedHashMap();
person.put("first_name", "Bob");
person.put("last_name", "SmithFoo");
payload.put("person", person);
LinkedHashMap response = client.put(payload, LinkedHashMap.class);

How to map Java HashMap<String, Pojo> variableName to typescript

I am trying to figure out how to create Typescript interface for HashMap<String, Pojo> I have tried the below variations but:
export interface ServerResponse {
// forWhomAdd: Array<ForWhomAdd>; // size/length is undefined
// forWhomAdd: Map<string, Address>; // size/length is undefined
forWhomAdd: { [firstLastName: string]: Address }; // How do I access keys and values?
}
I'd prefer not to do this the third way because I'm loosing my types which I'm trying to define.
This is how it looks when I log it:
{testKey: {property: value, prop: value}}
So I can get the Object by:
let serRes: ServerResponse = data;
serRes.testKey // gives back the object
But I don't know keys and I need to loop over serRes.
Assuming your data has list of ServerResponse.
let serRes: Array<ServerResponse> = data;
But I don't know keys and I need to loop over serRes.
you can get the values of the Object with keys() method of Objectclass.
Object.keys(this.serRes).map(key => this.serRes[key])
UPDATE :
I have created stackblitz for your case check it here.

Unknown depth nested maps check key existence and get value

I have a hashmap of the following structure:-
mymap = {a:{b:{c:{d:{e}}}}
How do I check the existance of key "d" in hashmap mymap in the simplest way?
Is there any Java8 features that might come in handy here?
mymap.get( "a" )).get( "b" )..;
is not going to work because I don't know the level in which d is nested.
How do I check if d is present in the map, and get its value without this trailing call? Thanks in advance.
I have recently had a similar problem and managed to come up with a solution which works with any JSON depths.
It is a solution which transforms the String into a JsonNode Object and then tries to find the parent value of a given fieldName (in this case 'd'). The result returning something which is not null, will tell you if the value exists or not.
ObjectMapper mapper = new ObjectMapper();
String myMapJson = "{\"a\":{\"b\":{\"c\":{\"d\":{\"e\":\"\"}}}}"
JsonNode data = mapper.readTree(myMapJson);
if (((ObjectNode)data.findParent("d")) != null) {
// Do something if value is found
} else {
// Do something if value is not found
}
Hope this helps..
You can use the FasterXML-Jackson library, which gives you the simplicty of traversing over nesed json.
For example:
ObjectMapper mapper = new ObjectMapper(); // can reuse, share globally
String myMapJson = "{\"a\":{\"b\":{\"c\":{\"d\":{\"e\":\"\"}}}}"
JsonNode data = mapper.readTree(myMapJson);
boolean hasKey = data.has("d");
Or, if you already have the object as Map you can write it as json and then load it the same way above:
ObjectMapper mapper = new ObjectMapper(); // can reuse, share globally
String jsonData = mapper.writeValueAsString(myMapObject);
JsonNode data = mapper.readTree(jsonData);
boolean hasKey = data.has("d");
if (hasKey) {
JsonNode result = data.findValue("d");
}

json (gson) parse changes the type of data when parsing

I have a json string which looks something like this :
{"employees":[
{"firstName":"John", "lastName":"Doe"},
{"firstName":"Anna", "lastName":"Smith"},
{"firstName":"Peter", "lastName":"Jones"}
]}
When I use gson parser to convert that to a Map<String,String> map. The gson converts the type to Map<String,ArrayList>. And when I try to print the class name using System.out.println(map.get("employees").getClass().toString()). But this throws an exception - java.lang.ClassCastException: java.util.ArrayList cannot be cast to java.lang.String.
my code looks something like this
String npv = json_string_provided_above;
Map<String,String> mp = new HashMap<String, String>();
mp = new Gson().fromJson(npv,mp.getClass());
System.out.println(mp.get("employees").getClass().toString());
The json is given as input by user in string format(and it will always be a valid json string). And one thing is sure that I can't assume anything about the type of data. Because it will be provided by user.
So now actually I want that even If the user inputs something like arrays of string or arrays of objects. It should not convert the them to List,
Is there is a way I can hard code the type and keep them in Map<String,String>. so in the above example when I do map.get("employees") it should give me the [{"firstName":"John", "lastName":"Doe"},{"firstName":"Anna", "lastName":"Smith"},{"firstName":"Peter", "lastName":"Jones"}] as string not list. I am not sure how to do this.
Thank you for your help,
Jon is right, just use Map<String, Object>
String npv = json_string_provided_above;
Map<String,Object> mp = new HashMap<String, Object>();
mp = new Gson().fromJson(npv, mp.getClass());
System.out.println(mp.get("employees").toString());

Store multiple values in HashMap and get it later

I am storing a data in HashMap and getting the value in later stage.
HashMap<String, byte[]> hm = new HashMap<String, byte[]>();
Now, I want to store two more values into it. For example, I want to store info like below. Could someone please advise me, how can i modify the Hashmap to ahieve this way? I also require to read all these stored values and find some value from it in later stage.
Key 1
IPAddress
RandomNumber
Byte data
Key 2
IPAddress
RandomNumber
Byte data
Thank you!
You have to create a class with these properties:
class MyData{
private String IPAddress;
private long RandomNumber;
private byte[] data;
//getters setters...
}
Map<String, MyData> hm = new HashMap<String, MyData>();
You can get the values as:
MyData dataObj = hm.get("Key 1");
dataObj.getRandomNumber();
or directly
hm.get("Key 1").getData();
hm.get("Key 1").getRandomNumber();
To iterate over the map:
Iterator it = hm.entrySet().iterator();
while (it.hasNext()) {
Map.Entry myDataEntry = (Map.Entry)it.next();
System.out.println(myDataEntry.getKey() + " = " + myDataEntry.getValue());
it.remove(); // avoids a ConcurrentModificationException
}
Taken from here: Iterate through a HashMap
Create a class like:
public class Key{
int randomNumber;
byte[] data;
String ipAddress;
}
And store it like a value of your Map.
Map<String, Key> map;
Hope it helps.
I see two options for your issue:
1 - make a bean to wrap all the needed content (as advised by other posters)
2 - if you want to have more values for a single key and adding a new library to your project is not an issue you can use google guava library, more particularly the Multimap class. There you can have more values for a single key.
Nevertheless I would advise in writing a java bean that wraps the content you want in a single object.

Categories

Resources