How to de-serialize Json to Map of Map? - java

I want to deserialize a json into
Map<String, Map<String, String>
This is the json structure that i want to convert.
{
"filetype": {
"cell": "value"
},
"fileType2": {
"cell2": "value2"}
}
I tried creating a class with Map<String, Map<String, String> type and tried with ObjectMapper(com.fasterxml.jackson.databind.ObjectMapper) in jackson:
class MapOfMap {
Map<String, Map<String, String>> mapOfMap;
//getter and setter
}
objectMapper.readValue(
new File(this.getClass()
.getClassLoader()
.getResource("configs/sample.json").getFile()),
MapOfMap.class
)
I am getting this error:
Unrecognized field "fileType".
Is there any way to do this?

You don't have to write a wrapping class around your Map. Just tell the Mapper you want a Map:
String jsonString = "{\n" +
" \"filetype\": {\n" +
" \"cell\": \"value\"\n" +
" },\n" +
" \"fileType2\": {\n" +
" \"cell2\": \"value2\"}\n" +
" }";
Map<String, Map<String, String>> map;
ObjectMapper mapper = new ObjectMapper();
try {
map = mapper.readValue(
jsonString,
new TypeReference<Map<String, Map<String, String>>>(){}
);
System.out.println(map);
} catch (Exception e) {
e.printStackTrace();
}
It prints: {filetype={cell=value}, fileType2={cell2=value2}}, which looks like what you want.
For reference: this

jackson
to Map
public static HashMap<String,Object> jsonToMap(String json) throws IOException {
JsonFactory factory = new JsonFactory();
ObjectMapper mapper = new ObjectMapper(factory);
TypeReference<HashMap<String,Object>> typeRef = new TypeReference<HashMap<String,Object>>() {};
return mapper.readValue(json, typeRef);
}
to Object:
public static <T> T jsonToObject(String json, Class<T> clazz) throws IOException {
ObjectMapper mapper = new ObjectMapper();
return mapper.readValue(json, clazz);
}

using gson:
String json = "{\n" +
" \"filetype\": {\n" +
" \"cell\": \"value\"\n" +
" },\n" +
" \"fileType2\": {\n" +
" \"cell2\": \"value2\"\n" +
" }\n" +
" }";
Gson gson = new GsonBuilder().create();
Map map = gson.fromJson(json, Map.class); //will be a map of maps
note that gson defaults to LinkedTreeMaps (so the order of iteration of elements is preserved)

Related

How do i pass a class as in the params in junits?

I have an API :
#RequestMapping(value = "/area/create",
method = RequestMethod.POST,
produces = MediaType.APPLICATION_JSON_VALUE)
#ResponseBody
public ResponseEntity<AreaEntry> createNewAreaEntry(
#RequestBody AreaRequestDto areaRequestDto) throws ServiceException {
UserContextHolder.setCustomer(areaRequestDto.getAreaEntry().getHost());
UserContextHolder.setSsoId(areaRequestDto.getUser());
AreaEntry newAreaEntryDto = service.createNewAreaEntry(areaRequestDto.getAreaEntry());
System.out.println("The area entries" + areaRequestDto.getUser()
+ " " + " "
+ areaRequestDto.getAreaEntry().getName()
+ " "
+ areaRequestDto.getAreaEntry().getCode() + " deugging");
System.out.println("the new area entry dto is" + newAreaEntryDto);
return new ResponseEntity<AreaEntry>(newAreaEntryDto, HttpStatus.OK);
I need to write a JUnit:
private List<String> getInvalidAreas(String areas) throws Exception {
ResultActions actions = mockMvc.perform(get("/area/create").param("cities", areas));
}
Where I need to pass the class arearequest dto in params
How do i do it?
You can simply pass json string, it will automatically deserialize and convert to DTO.
Or you can create utility method that convert your dto object to json and pass it as request body.
public String asJsonString(final Object obj) throws JsonProcessingException {
final ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
return mapper.writeValueAsString(obj);
}

Getting empty JSON using Jackson [duplicate]

This question already exists:
How to use Jackson Serializer when you don't know the property names [duplicate]
Closed 4 years ago.
Right now I'm trying to parse incoming JSON that is in this format:
{
<email>: {
<name>: <string>, # setting value
...
},
...
}
For example:
{
"aaa#example.com": {
"statement": true
},
"bbb#example.com": {
"statement": false
}
}
I also will not know how many emails will be in this JSON. I am a little befuddled as to how you could get all these emails with Jackson without knowing the property name for this, and I was wondering if it was possible.
Here is my code so far:
public class GDPRConsent extends Model {
#JsonIgnore
private static final String GDPR_CONSENT = "gdprConsent";
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
#JsonProperty
private ArrayList<String> emails;
#JsonProperty("serviceDataCollection")
private String dataCollection;
#JsonProperty("serviceDataCollection")
public String getDataCollectionConsent() {
return dataCollection;
}
#JsonProperty
public ArrayList<String> getEmails() {
return emails;
}
#JsonAnyGetter
public Map<String, Object> getAdditionalProperties() {
return this.additionalProperties;
}
#Override
public String getId() {
return GDPR_CONSENT;
}
}
Here is my parser:
public static <T> T parseObject(String sourceJson, Class<T> classToParse) {
T parsedObject = null;
try {
parsedObject = sObjectMapper.readValue(sourceJson, classToParse);
} catch (JsonParseException e) {
LogUtils.d(LOG_TAG, "parseObject JsonParseException: " + e.toString());
} catch (JsonMappingException e) {
LogUtils.d(LOG_TAG, "parseObject JsonMappingException: " + e.toString());
} catch (IOException e) {
LogUtils.d(LOG_TAG, "parseObject IOException: " + e.toString());
}
return parsedObject;
}
I am currently getting an empty result returned even though I know the JSON is being passed in.
If your JSON only includes the data given in your example, then it corresponds to a TypeReference<Map<String, Map<String, Boolean>>>, which is basically a mapping of strings to a mapping of strings to booleans. An example parser looks like this (no extra POJOs required):
import java.io.IOException;
import java.util.Map;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
public class JSONParser {
static final String TEST_JSON = "{"
+" \"aaa#example.com\": {"
+" \"statement\": true"
+"},"
+"\"bbb#example.com\": {"
+" \"statement\": false"
+"}"
+"}";
public static void main (String... args) {
ObjectMapper mapper = new ObjectMapper();
try {
Map<String, Map<String, Boolean>> jsonAsNestedMap = mapper.readValue(
TEST_JSON, new TypeReference<Map<String, Map<String, Boolean>>>() {
});
System.out.println(jsonAsNestedMap);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
This will print out
{aaa#example.com={statement=true}, bbb#example.com={statement=false}}
If the innermost values of your JSON are more complex, then you can use TypeReference<Map<String, Map<String, Object>>>:
static final String TEST_JSON = "{"
+" \"aaa#example.com\": {"
+" \"statement\": true,"
+" \"another_property\" : \"value 1\""
+"},"
+"\"bbb#example.com\": {"
+" \"statement\": false,"
+" \"another_property\" : \"value 2\""
+"}"
+"}";
//...
public static void main (String... args) {
//...
Map<String, Map<String, Object>> jsonAsNestedMap = mapper.readValue(
TEST_JSON, new TypeReference<Map<String, Map<String, Object>>>() {
});
//...
}
Accessing individual properties is possible through normal map iteration and accessor methods:
for (Entry<String, Map<String, Object>> e : jsonAsNestedMap.entrySet()) {
System.out.println("email:" + e.getKey() + ", another_property: "
+ e.getValue().get("another_property"));
}
which would give
email:aaa#example.com, another_property: value 1
email:bbb#example.com, another_property: value 2
I'm trying to parse incoming JSON that is in this format
As already explained in your duplicate question, you can parse into a Map.
public class EmailData {
private boolean statement;
public boolean isStatement() {
return this.statement;
}
public void setStatement(boolean statement) {
this.statement = statement;
}
#Override
public String toString() {
return "EmailData[statement=" + this.statement + "]";
}
}
Test
String json = "{" +
"\"aaa#example.com\": {" +
"\"statement\": true" +
"}," +
"\"bbb#example.com\": {" +
"\"statement\": false" +
"}" +
"}";
ObjectMapper mapper = new ObjectMapper();
TypeReference<HashMap<String, EmailData>> typeRef = new TypeReference<>() {/**/};
HashMap<String, EmailData> emails = mapper.readValue(json, typeRef);
System.out.println(emails);
Output
{aaa#example.com=EmailData[statement=true], bbb#example.com=EmailData[statement=false]}
If you prefer the #JsonAnySetter approach, you can do something like this:
public class Content {
private List<EmailData> emailData = new ArrayList<>();
#JsonAnySetter
public void addEmail(String name, EmailData value) {
value.setEmail(name);
this.emailData.add(value);
}
#Override
public String toString() {
return this.emailData.toString();
}
}
public class EmailData {
private String email;
private boolean statement;
#JsonIgnore
public String getEmail() {
return this.email;
}
public void setEmail(String email) {
this.email = email;
}
public boolean isStatement() {
return this.statement;
}
public void setStatement(boolean statement) {
this.statement = statement;
}
#Override
public String toString() {
return "EmailData[email=" + this.email + ", statement=" + this.statement + "]";
}
}
Test
String json = "{" +
"\"aaa#example.com\": {" +
"\"statement\": true" +
"}," +
"\"bbb#example.com\": {" +
"\"statement\": false" +
"}" +
"}";
ObjectMapper mapper = new ObjectMapper();
Content content = mapper.readValue(json, Content.class);
System.out.println(content);
Output
[EmailData[email=aaa#example.com, statement=true], EmailData[email=bbb#example.com, statement=false]]

Json to Java Mapping

I want to map below Json data to java object of List<Map<String, String>> type.
Sample Json:
{
{
a:b,
c:d
},
{
e:f,
g:h,
i:j
},
{
h:k
}
}
Here a:b represents key-value pair. So a:b and c:d will be mapped to first map of the list and so on.
one way to do this is by building JSON tree and access each node and store the pair into the map.
Is there a better way to do this (cleaner approach)?
Here is the code to read a List<Map<String, String>> using the Jackson library, with your example data as input:
public class JsonTest {
public static void main(String[] args) throws Exception {
final String json
= "[\n"
+ " {\n"
+ " \"a\":\"b\",\n"
+ " \"c\":\"d\"\n"
+ " },\n"
+ " {\n"
+ " \"e\":\"f\",\n"
+ " \"g\":\"h\",\n"
+ " \"i\":\"j\"\n"
+ " },\n"
+ " {\n"
+ " \"h\":\"k\"\n"
+ " }\n"
+ "]"; // [{a:b,c:d},{e:f,g:h,i:j},{h:k}]
ObjectMapper mapper = new ObjectMapper();
TypeFactory factory = TypeFactory.defaultInstance();
List<Map<String, String>> list = mapper.readValue(json,factory
.constructCollectionType(List.class, factory
.constructMapType(Map.class, String.class, String.class)));
System.out.println(list.toString());
}
}
Note: I had to fix your outermost braces from {} to [], which is the correct JSON list syntax.
You can use Jackson to achieve this task through below example code
public class JacksonExample {
public static void main(String[] args) {
ObjectMapper mapper = new ObjectMapper();
try {
// Convert JSON string from file to Object
User user = mapper.readValue(new File("C:\\user.json"), User.class);
System.out.println(user);
// Convert JSON string to Object
String jsonInString = "{\"age\":33,\"messages\":[\"msg 1\",\"msg 2\"],\"name\":\"xyz\"}";
User user1 = mapper.readValue(jsonInString, User.class);
System.out.println(user1);
} catch (JsonGenerationException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
First I made few changes to your json to make it valid
{
"key":
[{
"a": "b",
"c": "d"
},
{
"e": "f",
"g": "h",
"i": "j"
},
{
"h": "k"
}]
}
Please find the below code that I have tried out :
ObjectMapper mapper = new ObjectMapper();
ObjectNode objectNode1 = mapper.createObjectNode();
Map<String, Object> i = mapper.readValue(new File("J:/temp/sample.json"), Map.class);
System.out.println(i.get("key"));
System.out.println(i.values());
Output :
//For System.out.println(i.get("key"));
[{a=b, c=d}, {e=f, g=h, i=j}, {h=k}]
//For System.out.println(i.values());
[[{a=b, c=d}, {e=f, g=h, i=j}, {h=k}]]
If the above approach helps you, Make a right decision based on your needs either i.get("key") or i.values()
Just use gson library to Json to object and object to Json
import java.lang.reflect.Type;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
Object to Json
Gson gson = new Gson();
Student obj=new Student();
String jsonInString = gson.toJson(obj);
Json To Object
Student obj = gson.fromJson(jsonInString, Student.class);

How to dynamically handle json response array/object using Gson

I am facing a problem , sometimes Json response returns an array of objects , sometimes object itself , how we can handle dynamically in the response class.
In the current eg :results sometimes gets an array of objects
"\"results\": " +
"[{" +
and sometimes object itself
"\"results\": " +
"{" +
Eg:
How we can handle this ?
Gson gson = new Gson();
SearchResponse response=new SearchResponse();
response= gson.fromJson("{" +
"\"completed_in\": 0.047," +
"\"max_id\": 291771567376039936," +
"\"max_id_str\": \"291771567376039936\"," +
"\"next_page\": \"?page=2&max_id=291771567376039936&q=javacodegeeks\"," +
"\"page\": 1," +
"\"query\": \"javacodegeeks\"," +
"\"refresh_url\": \"?since_id=291771567376039936&q=javacodegeeks\"," +
"\"results\": " +
"{" +
"\"created_at\": \"Thu, 17 Jan 2013 04:58:57 +0000\"," +
"\"from_user\": \"hkokko\"," +
"\"from_user_id\": 24726686," +
"\"from_user_id_str\": \"24726686\"," +
" \"from_user_name\": \"Hannu Kokko\"," +
" \"geo\": null," +
"\"id\": 291771567376039936," +
"\"id_str\": \"291771567376039936\"," +
"\"iso_language_code\": \"en\"," +
" \"metadata\": {" +
"\"result_type\": \"recent\"}," +
"\"profile_image_url\": \"hjh\"," +
"\"profile_image_url_https\": \"kkj\"," +
"\"source\": \"<a href="hj;\"," +
"\"text\": \"Continuous Deployment: Are You Afraid It Might Work? jh\"," +
"\"to_user\": null," +
"\"to_user_id\": 0," +
"\"to_user_id_str\": \"0\"," +
"\"to_user_name\": null" +
" }," +
"\"results_per_page\": 15," +
"\"since_id\": 0," +
"\"since_id_str\": \"0\"" +
"}", SearchResponse.class);
System.out.println(response.toString());
Kindly assist...
Can anyone give any suggestions by using different jars to achieve this?
i found a solution for this ,i felt to share this..The code will automatically convert ..if excepted response is arraylist in response class....then if object is coming in response then add to arraylist else if arraylist it will take the same list.
we need hook change the response bfore it calls fromJson.
public class ArrayAdapter<T> extends TypeAdapter<List<T>> {
private Class<T> adapterclass;
public ArrayAdapter(Class<T> adapterclass) {
this.adapterclass = adapterclass;
}
public List<T> read(JsonReader reader) throws IOException {
List<T> list = new ArrayList<T>();
Gson gson = new Gson();
if (reader.peek() == JsonToken.BEGIN_OBJECT) {
T inning = (T) gson.fromJson(reader, adapterclass);
list.add(inning);
} else if (reader.peek() == JsonToken.BEGIN_ARRAY) {
reader.beginArray();
while (reader.hasNext()) {
T inning = (T) gson.fromJson(reader, adapterclass);
list.add(inning);
}
reader.endArray();
} else {
reader.skipValue();
}
return list;
}
public void write(JsonWriter writer, List<T> value) throws IOException {
}
}
public class ArrayAdapterFactory implements TypeAdapterFactory {
#SuppressWarnings({ "unchecked" })
#Override
public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> type) {
ArrayAdapter typeAdapter = null;
try {
if (type.getRawType() == List.class)
{
typeAdapter = new ArrayAdapter(
(Class) ((ParameterizedType) type.getType())
.getActualTypeArguments()[0]);
}
} catch (Exception e) {
e.printStackTrace();
}
return typeAdapter;
}
then just call
Gson gson = new GsonBuilder().registerTypeAdapterFactory(new ArrayAdapterFactory()).create();
SearchResponse response;
esponse= gson.fromJson("your json string", SearchResponse.class)
You would need to write a custom deserializer that checks the type of results in the JSON then acts accordingly.
Your POJO will contain an array for results and if your incoming JSON only has a single object you'll need to fix that. One way is to modify the JSON then deserialize it:
class SearchResponseDeserializer implements JsonDeserializer<SearchResponse> {
public SearchResponse deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
if (json.getAsJsonObject().get("results").isJsonObject()) {
//modify JSON: change results to be an array
// ...
}
return new Gson().fromJson(json, SearchResults.class);
}
}
Or, fix the server, of course. It should always be returning an array to avoid this issue.

Map to JSON in Java

i have a map like this
MAP:
{
facility-1={
facility-kind1={param1=XPath-1, param2=XPath-2},
facility-kind2={param1=XPath-1, param2=XPath-2},
facility-kind3={param1=XPath-1, param2=XPath-2}
},
facility-2={
facility-kind1={param1=XPath-1, param2=XPath-2},
facility-kind2={param1=XPath-1, param2=XPath-2},
facility-kind3={param1=XPath-1, param2=XPath-2}
}
}
I want to convert it into JSON formated like this
[
{"title": "Item 1"},
{"title": "Folder 2",
"children": [
{"title": "Sub-item 2.1"},
{"title": "Sub-item 2.2"}
]
},
{"title": "Folder 3",
"children": [
{"title": "Sub-item 3.1"},
{"title": "Sub-item 3.2"}
]
},
{"title": "Item 5"}
]
I tried to use GSON But the resulting output was not what I wanted:
{
"facility-1": {
"facility-kind1":
{"param1":"XPath-1","param2":"XPath-2"},
"facility-kind2":
{"param1":"XPath-1","param2":"XPath-2"},
"facility-kind3":
{"param1":"XPath-1","param2":"XPath-2"}
},
"facility-2": {
"facility-kind1":
{"param1":"XPath-1","param2":"XPath-2"},
"facility-kind2":
{"param1":"XPath-1","param2":"XPath-2","param3":"XPath-3"},
"facility-kind3":
{"param1":"XPath-1","param2":"XPath-2"}
}
}
how can a get a json formated as i want??
You need to transform your JSON to the new format you have provided.
Data to convert:
static String json =
"{\n" +
" facility-1={\n" +
" facility-kind1={param1=XPath-1, param2=XPath-2},\n" +
" facility-kind2={param1=XPath-1, param2=XPath-2},\n" +
" facility-kind3={param1=XPath-1, param2=XPath-2}\n" +
" },\n" +
" facility-2={\n" +
" facility-kind1={param1=XPath-1, param2=XPath-2},\n" +
" facility-kind2={param1=XPath-1, param2=XPath-2},\n" +
" facility-kind3={param1=XPath-1, param2=XPath-2}\n" +
" }\n" +
"}\n";
Using GSON
Create some classes that you want to handle the data, they can look something like:
static class Facility {
List<Kind> children = new LinkedList<Kind>();
}
static class Kind {
String title;
Map<String, String> params;
public Kind(String title, Map<String, String> params) {
this.title = title;
this.params = params;
}
}
The next step is too look at the source and create a represenatation of it. I would use:
Map<String, Map<String, Map<String, String>>>
since the input data is layed out like it. To convert it using Gson now is quite easy:
public static void main(String... args) throws Exception {
Gson gson = new GsonBuilder().setPrettyPrinting().create();
Type type = new TypeToken<
Map<String, Map<String, Map<String, String>>>>() {}.getType();
Map<String, Map<String, Map<String, String>>> source =
gson.fromJson(json, type);
Map<String, Facility> dest = new HashMap<String, Facility>();
for (String facilityName : source.keySet()) {
Map<String, Map<String, String>> facility = source.get(facilityName);
Facility f = new Facility();
for (String kindName : facility.keySet())
f.children.add(new Kind(kindName, facility.get(kindName)));
dest.put(facilityName, f);
}
System.out.println(gson.toJson(dest));
}
Using JSONObject/JSONArray
public static void main(String... args) throws Exception {
JSONObject source = new JSONObject(json);
JSONArray destination = new JSONArray();
for (Iterator<?> keys = source.keys(); keys.hasNext(); ) {
String facilityName = (String) keys.next();
JSONObject kinds = source.getJSONObject(facilityName);
JSONArray children = new JSONArray();
for (Iterator<?> kit = kinds.keys(); kit.hasNext(); ) {
String kind = (String) kit.next();
JSONObject params = kinds.getJSONObject(kind);
JSONObject kindObject = new JSONObject();
kindObject.put("title", kind);
for (Iterator<?> pit = params.keys(); pit.hasNext(); ) {
String param = (String) pit.next();
kindObject.put(param, params.get(param));
}
children.put(kindObject);
}
JSONObject facility = new JSONObject();
facility.put("title", facilityName);
facility.put("children", children);
destination.put(facility);
}
System.out.println(destination.toString(2));
}
What you want is pretty printing.
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String json = gson.toJson(yourMap);

Categories

Resources