MulitvaluedMap<String, String> to MultivaluedMap<String, Object> - java

I have a MultivaluedMap<String, String> strMap which i want to convert to MultivaluedMap<String, Object> objMap.
I tried exploring a few routes in the post below but none of them seem to work.
Converting Map<String,String> to Map<String,Object>

I had the same issue today, after a lot of searching, I came up with the following solutions:
public static MultivaluedMap<String, Object> asObjectHeaders(MultivaluedMap<String, String> headers) {
if (headers == null) {
return null;
} else {
MultivaluedMap<String, Object> map = new MultivaluedHashMap<>();
for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
if (entry.getValue() != null) {
map.addAll(entry.getKey(), new LinkedList<Object>(entry.getValue()));
}
}
return map;
}
}
OR If you are using Guava, then you can use the following code:
public static MultivaluedMap<String, Object> asObjectHeaders(MultivaluedMap<String, String> headers) {
if (headers == null) {
return null;
} else {
return new AbstractMultivaluedMap<String, Object>(Maps.transformValues(headers, new Function<List<String>, List<Object>>() {
#Override
public #Nullable List<Object> apply(#Nullable List<String> strings) {
if (strings != null) {
return new LinkedList<>(strings);
} else {
return null;
}
}
})) {};
}
}
OR If you are using jersey client glassfish, then you can use the following:
public static MultivaluedMap<String, Object> asObjectHeaders(MultivaluedMap<String, String> headers) {
if (headers == null) {
return null;
} else {
return new AbstractMultivaluedMap<String, Object>(Views.mapView(headers, LinkedList::new)) {};
}
}

Had the same situation, Working solution-
MultiValuedMap<String, String> multivaluedMap = //store the value here
Collection<Map.Entry<String, String>> entries = multivaluedMap.entries();
for(Map.Entry<String, String> ent : multivaluedMap.entries()){
entityList.add(ent.getKey()+ " " + ent.getValue());
}

Related

Java flatten nested Maps and concatenate keys

I have a HashMap as below:
Map<String,Object> map = new HashMap<>();
Map<String,Object> map1 = new HashMap<>();
map1.put("key1", "value1");
Map<String,Object> map2 = new HashMap<>();
Map<String,Object> map3 = new HashMap<>();
map3.put("key2", "value2");
map2.put("map3", map3);
map.put("map1", map1);
map.put("map2", map2);
map.put("key3", "value3");
I want to flatten it. Expected output is:
[map1.key1, value1]
[map2.map3.key2, value2]
[key3, value3]
...
This can be done using simple for loops with following code:
public static Map<String, String> flat(Map<String, Object> input){
Map<String, String> toReturn = new HashMap<>();
for (Map.Entry<String, Object> entry: input.entrySet()) {
if(entry.getValue() instanceof Map){
Map<String, Object> innerMap = (Map<String, Object>)entry.getValue();
for(Map.Entry<String, Object> innerEntry: innerMap.entrySet()) {
if(innerEntry.getValue() instanceof Map){
...
...
}
else {
toReturn.put(entry.getKey() + "." + innerEntry.getKey(), innerEntry.getValue().toString());
}
}
} else {
toReturn.put(entry.getKey(), entry.getValue().toString());
}
}
return toReturn;
}
Code to do this recursively:
public static Map<String, String> flat(Map<String, Object> input){
Map<String, String> toReturn = new HashMap<>();
rec(toReturn, input, new ArrayList<>());
return toReturn;
}
public static void rec(Map<String, String> toReturn, Map<String, Object> input, List<String> keys) {
for (Map.Entry<String, Object> entry: input.entrySet()) {
if(entry.getValue() instanceof Map){
keys.add(entry.getKey());
rec(toReturn, (Map<String, Object>) entry.getValue(), keys);
} else {
final StringBuffer key = new StringBuffer();
if(keys.size() > 0) {
keys.forEach(x -> key.append(x).append("."));
}
key.append(entry.getKey());
toReturn.put(key.toString(), entry.getValue().toString());
}
}
if(keys.size() > 0) {
keys.remove(keys.size() - 1);
}
}
How do I achieve this using Java Stream API ?
This is generally the same solution as in the mentioned link but with some update to work with entrySet() and add a key from containing map as a prefix:
public class FlattenMap {
public static Stream<Map.Entry<String, Object>> flatten(Map.Entry<String, Object> entry) {
if (entry.getValue() instanceof Map<?, ?>) {
Map<String, Object> nested = (Map<String, Object>) entry.getValue();
return nested.entrySet().stream()
.map(e -> new AbstractMap.SimpleEntry(entry.getKey() + "." + e.getKey(), e.getValue()))
.flatMap(FlattenMap::flatten);
}
return Stream.of(entry);
}
public static void main(String[] args) {
Map<String,Object> map = new HashMap<>();
Map<String,Object> map1 = new HashMap<>();
map1.put("key1", "value1");
Map<String,Object> map2 = new HashMap<>();
Map<String,Object> map3 = new HashMap<>();
map3.put("key2", "value2");
map2.put("map3", map3);
map.put("map1", map1);
map.put("map2", map2);
map.put("key3", "value3");
// collecting to List of entries
map.entrySet().stream()
.flatMap(FlattenMap::flatten)
.collect(Collectors.toList())
.forEach(System.out::println);
// collecting entries back to flattened map
Map<String, Object> remapped = map.entrySet().stream()
.flatMap(FlattenMap::flatten)
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
remapped.entrySet().stream()
.forEach(e -> System.out.printf("[%s, %s]%n", e.getKey(), e.getValue()));
}
}
It prints results:
map2.map3.key2=value2
map1.key1=value1
key3=value3
[key3, value3]
[map2.map3.key2, value2]
[map1.key1, value1]

Restructuring JSON file in JAVA

I am having the following sample from a JSON file:
[
{
"0":
{
"File":"file1.java",
"Class":"com.ETransitionActionType",
"Method":"values",
"Annotation":"Not Found"
}
},
{
"1":
{
"File":"file2.java",
"Class":"com.ETransitionParams",
"Method":"values",
"Annotation":"Not Found"
}
},
{
"2":
{
"File":"file3.java",
"Class":"com.phloc.commons.id.IHasID",
"Method":"getID",
"Annotation":"Not Found"
}
},
{
"4":
{
"File":"file3.java",
"Class":"com.ExecuteTransitionActionHandler",
"Method":"createBadRequestResponse",
"Annotation":"Not Found"
}
},
{
"5":
{
"File":"file3.java",
"Class":"com.ExecuteTransitionActionHandler",
"Method":"extractParametersFromAction",
"Annotation":"Not Found"
}
}]
How can I restructure this file using java so that it looks like:
[{
"file1.java": {
"com.ETransitionActionType": {
"values": {
"Annotation": "Not Found"
}
}
}
},
{
"file2.java": {
"com.ETransitionParams": {
"values": {
"Annotation": "Not Found"
}
}
}
},
{
"file3.java": {
"com.phloc.commons.id.IHasID": {
"getID": {
"Annotation": "Not Found"
}
},
"com.ExecuteTransitionActionHandler": {
"getID": {
"Annotation": "Not Found"
},
"extractParametersFromAction": {
"Annotation": "Not Found"
}
}
}
}
]
i.e. Going through the JSON file, searching it, and wherever the "File" attribute has the same value("file3.java" for example), we list all the relevant classes and methods inside and the same applies for the "Class" attribute, if it has the same name, we list all the methods inside it(So it's like comparing and sorting the values for the "File" and "Class" attributes).
I started with JSON simple library and wrote like the code below, but don't know how to go further!
Object object = (JSONArray)parser.parse(new FileReader("rawOutput.json"));
JSONArray jsonArray = (JSONArray) object;
for(int i = 0; i < jsonArray.size(); i++) {
System.out.println(jsonArray.get(i));
JSONObject jsonObject = (JSONObject)jsonArray.get(i);
String c = jsonObject.get("" + i + "").toString();
}
Any ideas? Your help is really appreciated!!!
I wrote a code to do what do you need but first you have to add this library to your project if you don't have already org.json.zip library, because I didn't have a library for parsing Json texts so I used this library for formatting the Json data, and I'm sorry if you don't understand the code completely because your request isn't so easy as yourself know and I created three functions to get the result and although I wrote some comments to understand easily, this is the code:-
Edit
...
import org.json.*;
...
...
public static void main(String[] args) throws JSONException {
System.out.println(getFormattedJson("json text"));
}
private static String getFormattedJson(String text) throws JSONException{
JSONArray result = new JSONArray();
JSONArray jsonArray = null;
//get the json array
jsonArray = new JSONArray(text);
//loop through items in the array and insert them formatted to the result
for (int i = 0; i < jsonArray.length(); i++) {
//get object inside the number
JSONObject object = getJsonChild(jsonArray.getJSONObject(i));
//get these attributes
String file = object.getString("File");
String clas = object.getString("Class");
String meth = object.getString("Method");
String anno = object.getString("Annotation");
//create a custom type of the object's attributes
Map<String, String> map = new HashMap<>();
map.put("Annotation", anno);
Map<String, Object> map1 = new HashMap<>();
map1.put(meth, map);
Map<String, Object> map2 = new HashMap<>();
map2.put(clas, map1);
Map<String, Object> map3 = new HashMap<>();
map3.put(file, map2);
//loop through repeating values to also add them to one value as you expected
for (int j = jsonArray.length() - 1; j > i; j--) {
JSONObject obj = getJsonChild(jsonArray.getJSONObject(j));
String file1 = obj.getString("File");
String clas1 = obj.getString("Class");
String meth1 = obj.getString("Method");
String anno1 = obj.getString("Annotation");
if (file1.equals(file)) {
if (map2.containsKey(clas1)) {
if (childrenContains(map2, meth1)) {
//if the difference was annotation value
map.put("Annotation", anno1);
} else {
//if the difference was method names
Map<String, String> map_ = new HashMap<>();
map_.put("Annotation", anno1);
((Map<String, Object>) map2.get(clas1)).put(meth1, map_);
}
} else {
//if the difference was class names
Map<String, String> map_ = new HashMap<>();
map_.put("Annotation", anno1);
Map<String, Object> map1_ = new HashMap<>();
map1_.put(meth1, map_);
map2.put(clas1, map1_);
}
//remove the (value added) object
jsonArray.remove(j);
}
}
//add the map to the result
result.put(map3);
}
return result.toString(4);
}
private static boolean childrenContains(Map<String, Object> map1, String meth1) {
for (String childKey : map1.keySet()) {
Map<String, Object> child = (Map<String, Object>) map1.get(childKey);
if (child.containsKey(meth1))
return true;
}
return false;
}
private static JSONObject getJsonChild(JSONObject object) throws JSONException {
Iterator<String> keys = object.keys();
String key = "";
while (keys.hasNext()) {
key = (String) keys.next();
}
return object.getJSONObject(key);
}
And the result for your sample using my code is:-
[
{"file1.java": {"com.ETransitionActionType": {"values": {"Annotation": "Not Found"}}}},
{"file2.java": {"com.ETransitionParams": {"values": {"Annotation": "Not Found"}}}},
{"file3.java": {
"com.ExecuteTransitionActionHandler": {
"createBadRequestResponse": {"Annotation": "Not Found"},
"extractParametersFromAction": {"Annotation": "Not Found"}
},
"com.phloc.commons.id.IHasID": {"getID": {"Annotation": "Not Found"}}
}}
]
And if you want to get the json data from a file so use the following function to create the JSONArray easily:-
private static JSONArray readFromFile(String filePath){
try {
BufferedReader br = new BufferedReader(new FileReader(filePath));
StringBuilder sb = new StringBuilder();
String line = br.readLine();
while (line != null) {
sb.append(line);
sb.append(System.lineSeparator());
line = br.readLine();
}
return new JSONArray(sb.toString());
} catch (Exception e) {
System.out.println(e.getMessage());
return null;
}
}
And use it instead the text json data:-
...
//get the json array
jsonArray = readFromFile("FilePath");
...
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
public class Foo {
public static void main(String... args) throws IOException {
String json = formatJson(new FileReader("rawOutput.json"));
System.out.println(json);
}
public static String formatJson(Reader reader) throws IOException {
// group array items by fileName
final Function<List<Map<String, Object>>, Map<String, List<Object>>> groupByFileName =
data -> data.stream().collect(Collectors.groupingBy(map -> (String)map.get("File"), TreeMap::new,
Collectors.mapping(Function.identity(), Collectors.toList())));
// convert source item structure into required
final Function<Map.Entry<String, List<Object>>, Map<String, Object>> convert = entry -> {
Map<String, Map<String, Map<String, String>>> tmp = new LinkedHashMap<>();
entry.getValue().stream()
.map(value -> (Map<String, String>)value)
.forEach(map -> {
Map<String, Map<String, String>> classes = tmp.computeIfAbsent(map.get("Class"), cls -> new TreeMap<>());
Map<String, String> methods = classes.computeIfAbsent(map.get("Method"), method -> new TreeMap<>());
map.entrySet().stream()
.filter(e -> !"Class".equals(e.getKey()) && !"Method".equals(e.getKey()) && !"File".equals(e.getKey()))
.forEach(e -> methods.put(e.getKey(), e.getValue()));
});
return Collections.singletonMap(entry.getKey(), tmp);
};
ObjectMapper mapper = new ObjectMapper();
// read json as array of Maps
List<Map<String, Object>> data = Arrays.stream(mapper.readValue(reader, Map[].class))
.map(map -> map.values().iterator().next())
.map(item -> (Map<String, Object>)item)
.collect(Collectors.toList());
return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(groupByFileName.apply(data).entrySet().stream()
.map(convert).collect(Collectors.toList()));
}
}
You could create a map of maps to represent your grouping by "File" and "Class" for your list of (inner) JSON objects. It might look similar to
final Function<JSONObject, String> fileFunction = (JSONObject jsonObject) -> jsonObject.getString("File");
final Function<JSONObject, String> classFunction = (JSONObject jsonObject) -> jsonObject.getString("Class");
final Map<String, Map<String, List<JSONObject>>> groupedJsonObjects = jsonObjects.stream()
.collect(Collectors.groupingBy(fileFunction, Collectors.groupingBy(classFunction)));

android-Volley JSONObjectRequest return 401 error

I'm trying to send a POST request with paramteres to server. But the post params are always null.
I've tried few solutions from stackoverflow but it didn't work.
I get Unexpected response code 401 for 11.urlname
Map<String, String> jsonParams = new HashMap<String, String>();
jsonParams.put("username", "test#mail.com");
jsonParams.put("usertype", "userType");
jsonParams.put("apikey", "key");
JsonObjectRequest myRequest = new JsonObjectRequest(Request.Method.POST,apiURL, new JSONObject(jsonParams),
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
String status=response.getString("status");
if (status.equals("success"))
{
txtResponse.setText("Valid user");
}
else {
txtResponse.setText("InValid USer");
}
} catch (JSONException e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}) {
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("Content-Type", "application/json; charset=UTF-8");
return headers;
}
};
AppController.getInstance().addToRequestQueue(myRequest, "tag");
My App controller code is
public class AppController extends Application {
public static final String TAG = AppController.class.getSimpleName();
private RequestQueue mRequestQueue;
private static AppController mInstance;
#Override
public void onCreate() {
super.onCreate();
mInstance = this;
}
public static synchronized AppController getInstance() {
return mInstance;
}
public RequestQueue getRequestQueue() {
if (mRequestQueue == null) {
mRequestQueue = Volley.newRequestQueue(getApplicationContext());
}
return mRequestQueue;
}
public <T> void addToRequestQueue(Request<T> req, String tag) {
req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
getRequestQueue().add(req);
}
public <T> void addToRequestQueue(Request<T> req) {
req.setTag(TAG);
getRequestQueue().add(req);
}
public void cancelPendingRequests(Object tag) {
if (mRequestQueue != null) {
mRequestQueue.cancelAll(tag);
}
}
}
If your issue has not been solved, you can refer to the following code to build your request body (params)
private String buildRequestBody(Object content) {
String output = null;
if ((content instanceof String) ||
(content instanceof JSONObject) ||
(content instanceof JSONArray)) {
output = content.toString();
} else if (content instanceof Map) {
Uri.Builder builder = new Uri.Builder();
HashMap hashMap = (HashMap) content;
if (isValid(hashMap)) {
Iterator entries = hashMap.entrySet().iterator();
while (entries.hasNext()) {
Map.Entry entry = (Map.Entry) entries.next();
builder.appendQueryParameter(entry.getKey().toString(), entry.getValue().toString());
entries.remove(); // avoids a ConcurrentModificationException
}
output = builder.build().getEncodedQuery();
}
}
return output;
}
Then...
Map<String, String> stringMap = new HashMap<>();
stringMap.put("username", "yourusername");
stringMap.put("password", "yourpassword");
...
String requestBody = buildRequestBody(stringMap);

Jackson ObjectMapper configuration - error JsonParseException: Unexpected character ('b' (code 98)):

I have generated JSON in the following format
[{"empNo":"2390","empName":"JAMES","projects":{"projectId":209,"projectName":"Z560"}}]
How do I configure ObjectMapper for the above?
I have declared ObjectMapper as
private static final ObjectMapper om = new ObjectMapper();
static {
om.configure(JsonGenerator.Feature.QUOTE_FIELD_NAMES, false);
om.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
om.configure(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS,
true);
om.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES,
false);
om.getSerializationConfig().setSerializationInclusion
(JsonSerialize.Inclusion.NON_NULL);
}
However I am still getting the following error
com.sun.jersey.spi.container.ContainerResponse mapMappableContainerException
SEVERE: The exception contained within MappableContainerException could not
be mapped to a response, re-throwing to the HTTP container
org.codehaus.jackson.JsonParseException: Unexpected character ('b' (code 98)):
expected a valid value (number, String, array, object,
'true', 'false' or 'null') at [Source: java.io.StringReader#1fef0b44; line: 1,
column: 2]
Expected output is
{"empNo":"2390","empName":"JAMES","projectId":"209","projectName":"Z560"}
A bit lengthy, can be optimized. refer this for more.
public static void main(String[] args) throws IOException {
String originalJson = "{\"empNo\":\"2390\",\"empName\":\"JAMES\",\"projects\":{\"projectId\":209,\"projectName\":\"Z560\"}}";
try {
JSONObject jsonObject = new JSONObject(originalJson);
Map<String, Object> map = getMap(jsonObject);
System.out.println("My Old Map => " + map);
Map<String, Object> newMap = new HashMap<String, Object>();
for (Map.Entry<String, Object> entry : map.entrySet()) {
if (entry.getKey().equals("projects")) {
Map<String, Object> projectMap = (Map<String, Object>) entry.getValue();
for (Map.Entry<String, Object> entry1 : projectMap.entrySet()) {
newMap.put(entry1.getKey(), entry1.getValue());
}
} else {
newMap.put(entry.getKey(), entry.getValue().toString());
}
}
JSONObject jsonObject1 = new JSONObject(newMap);
System.out.println("My New Map => " + newMap);
System.out.println("Expected Json String => " + jsonObject1.toString());
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private static Map getMap(JSONObject object) {
Map<String, Object> map = new HashMap<String, Object>();
Object jsonObject = null;
String key = null;
Object value = null;
try {
Iterator<String> keys = object.keys();
while (keys.hasNext()) {
key = null;
value = null;
key = keys.next();
if (null != key && !object.isNull(key)) {
value = object.get(key);
}
if (value instanceof JSONObject) {
map.put(key, getMap((JSONObject) value));
continue;
}
if (value instanceof JSONArray) {
JSONArray array = ((JSONArray) value);
List list = new ArrayList();
for (int i = 0 ; i < array.length() ; i++) {
jsonObject = array.get(i);
if (jsonObject instanceof JSONObject) {
list.add(getMap((JSONObject) jsonObject));
} else {
list.add(jsonObject);
}
}
map.put(key, list);
continue;
}
map.put(key, value);
}
} catch (Exception e) {
System.out.println(e);
}
return map;
}
Output
My Old Map => {projects={projectId=209, projectName=Z560},
empName=JAMES, empNo=2390}
My New Map => {empName=JAMES, empNo=2390, projectId=209,
projectName=Z560}
Expected Json String =>
{"empName":"JAMES","empNo":"2390","projectId":209,"projectName":"Z560"}

How to solve this incompatible types in java?

I get error in following lines.
error: incompatible types
required : java.util.Map.entry<java.lang.String,java.lang.String[]>
found :java.lang.Object
full code is below
package com.auth.actions;
public class SocialAuthSuccessAction extends Action {
final Log LOG = LogFactory.getLog(SocialAuthSuccessAction.class);
#Override
public ActionForward execute(final ActionMapping mapping,
final ActionForm form, final HttpServletRequest request,
final HttpServletResponse response) throws Exception {
AuthForm authForm = (AuthForm) form;
SocialAuthManager manager = null;
if (authForm.getSocialAuthManager() != null) {
manager = authForm.getSocialAuthManager();
}
if (manager != null) {
List<Contact> contactsList = new ArrayList<Contact>();
Profile profile = null;
try {
Map<String, String> paramsMap = new HashMap<String, String>();
for (Map.Entry<String, String[]> entry :request.getParameterMap().entrySet() ) { // error in this line!
String key = entry.getKey();
String values[] = entry.getValue();
paramsMap.put(key, values[0].toString()); // Only 1 value is
}
AuthProvider provider = manager.connect(paramsMap);
profile = provider.getUserProfile();
contactsList = provider.getContactList();
if (contactsList != null && contactsList.size() > 0) {
for (Contact p : contactsList) {
if (StringUtils.isEmpty(p.getFirstName())
&& StringUtils.isEmpty(p.getLastName())) {
p.setFirstName(p.getDisplayName());
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
request.setAttribute("profile", profile);
request.setAttribute("contacts", contactsList);
return mapping.findForward("success");
}
// if provider null
return mapping.findForward("failure");
}
}
Please help
You need to cast request.getParameterMap()to Map<String, String[]>
for (Map.Entry<String, String[]> entry :
((Map<String, String[]>)request.getParameterMap()).entrySet())
Try the following:
for (Object obj :request.getParameterMap().entrySet() ) {
Map.Entry<String, String[]> entry = (Map.Entry<String, String[]>) obj;
String key = entry.getKey();
String values[] = entry.getValue();
paramsMap.put(key, values[0].toString()); // Only 1 value is
}
Am not really sure this will work, anyway, you got the approach. Hope this helps.
As pointed out in the comments, getParameterMap() must be returning the raw type Map instead of Map<String, String[]>. This means getParameterMap().entrySet() returns raw Iterable, causing the compiler error.
If you want to avoid doing an explicit unchecked cast as the other answers suggest, an alternative is to use a variable assignment for unchecked conversion:
#SuppressWarnings("unchecked") // getParameterMap returns raw Map
Map<String, String[]> params = request.getParameterMap();
for (Map.Entry<String, String[]> entry : params.entrySet()) {
...
}

Categories

Resources