How do you serialize a map of keys-value pairs such that that the resulting JSON has the form:
["key1":"value1", "key2":"value2", "keyN":"valueN"]
The default way that a Map is serialized is in the form:
{"key1":"value1", "key2":"value2", "keyN":"valueN"}
The custom serializer that I tried to make seems to want to put them in separate objects as when I take the comments out of the below snippet
public class MapToArraySerializer extends JsonSerializer<Map<String,String>>
{
#Override
public void serialize(Map<String,String> additionalData, JsonGenerator generator, SerializerProvider provider) throws IOException
{
generator.writeStartArray();
for (String key : additionalData.keySet()) {
//generator.writeStartObject();
generator.writeObjectField(key, additionalData.get(key));
//generator.writeEndObject();
}
generator.writeEndArray();
}
}
I get the following:
com.fasterxml.jackson.core.JsonGenerationException: Can not write a field name, expecting a value
at com.fasterxml.jackson.core.JsonGenerator._reportError(JsonGenerator.java:1886)
at com.fasterxml.jackson.core.json.WriterBasedJsonGenerator.writeFieldName(WriterBasedJsonGenerator.java:126)
at com.fasterxml.jackson.core.JsonGenerator.writeObjectField(JsonGenerator.java:1651)
As #Henrik pointed out, this is not valid but I was able to accomplish this by using the #JsonRawValue annotation:
#JsonRawValue
public String getAdditionalData()
{
String json = "[";
List<String> keys = new ArrayList<>(additionalData.keySet());
for (int i = 0; i < keys.size(); i++) {
String key = keys.get(i);
json = json + "\"" + key + "\":\"" + additionalData.get(key) + "\"";
if (i + 1 < keys.size()) {
json = json + ",";
}
}
return json + "]";
}
Related
I have a java code that retrieves a bson.Document from MongoDB.
An example JSON/BSON document is:
{
"field1": "text1",
"field2": {
"field2Sub1": "text2"
}
}
In my java code I manipulate it like this to get values of field1 and field2Sub1
com.fasterxml.jackson.databind.ObjectMapper objectMapper;
org.bson.Document documentFromMongo = this.getDocumentFromMongo();
org.bson.Document field2Document = documentFromMongo.get("field2", Document.class);
String field1Value = objectMapper.convertValue(documentFromMongo.get("field1"), String.class);
String field2Sub1Value = objectMapper.convertValue(field2Document.get("field2Sub1"), String.class);
Is there any way or some library or method I can use to get the value of field2Sub1 like this way:
String field1Value = objectMapper.convertValue(documentFromMongo.get("field2.field2Sub1"), String.class);
I don't know of another library doing this, but you could use org.bson.Document provided functionality to achieve similar effect. It's quite simple
Split your input/path by dot
Use Document.getEmbedded()
Like so:
public class MongoMain {
private static final String JSON = "{\n" +
" \"field1\": \"text1\",\n" +
" \"field2\": {\n" +
" \"field2Sub1\": \"text2\"\n" +
" }\n" +
"}";
public static void main(String[] args) {
Document document = Document.parse(JSON);
String path = "field2.field2Sub1";
String value = extractValue(document, path);
System.out.println("extracted value - " + value);
}
private static String extractValue(Document document, String dotNotationPath) {
List<String> path = Arrays.asList(dotNotationPath.split("\\."));
return document.getEmbedded(path, String.class);
}
}
The extractValue method does the trick - first split by dot and build a list, because getEmbedded accepts a list, then getEmbedded handles the rest.
This question already has answers here:
How can I access each key and value in JSONArray
(2 answers)
Closed 7 years ago.
For example from the following json, id, items, fromNumber should be retrieved.
The json can be having n number of nesting.
{
"items": [{
"id": 633706061003,
"fromNumber": "16572307534",
"contact": {
"id": 499354453003,
"homePhone": "16572307534"
},
"records": [{
"id": 353389055003,
"result": "LA",
"recordings": [{
"id": 16427622003,
}]
}]
}],
"limit": 100,
"offset": 0,
"totalCount": 5949
}
I have implemented the below code, but in this code I have to tell the level of nesting
String prefix = "";
/*
* Root Array
*/
JsonArray rootArray = new JsonParser().parse(json).getAsJsonArray();
for (int i = 0; i < rootArray.size(); i++) {
/*
* Single object in root array while iterations. for id, properties, tags etc.
*/
JsonObject rootArrayObject = rootArray.get(i).getAsJsonObject();
Set<Map.Entry<String, JsonElement>> rootArrayObjectEntrySet = rootArrayObject.entrySet();
/*
* Getting the keys and values of RootArray Single Object
*/
for (Map.Entry<String, JsonElement> entryChild : rootArrayObjectEntrySet) {
prefix = entryChild.getKey();
/*
* Getting each object, key or array as an element
*/
JsonElement rootArrayObjElement = rootArrayObject.get(entryChild.getKey());
if(rootArrayObjElement.isJsonArray()){
/*
* Getting array's object in single object of root array. Example: tags
*/
JsonArray rootArrayObjArray = rootArrayObjElement.getAsJsonArray();
for (int j = 0; j < rootArrayObjArray.size(); j++) {
}
}else if(rootArrayObjElement.isJsonObject()){
/*
* Single object in root array
*/
JsonObject rootArrayObjObj = rootArrayObjElement.getAsJsonObject();
Set<Map.Entry<String, JsonElement>> rootArrayObjObjEntrySet = rootArrayObjObj.entrySet();
for (Map.Entry<String, JsonElement> rootArrayObjObjChild : rootArrayObjObjEntrySet) {
/*
* Getting each object, key or array as an element
*/
JsonElement rootArrayObjObjElement = rootArrayObjObj.get(rootArrayObjObjChild.getKey());
if(rootArrayObjObjElement.isJsonPrimitive()){
}else if(rootArrayObjObjElement.isJsonArray()){
JsonArray rootArrayObjArray = rootArrayObjObjElement.getAsJsonArray();
for (int j = 0; j < rootArrayObjArray.size(); j++) {
}
}
}
}else if(rootArrayObjElement.isJsonPrimitive()){
}
}
}
You can try something like below :
import com.google.gson.Gson;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
public class GSonWay {
public static void main(String[] args) throws Exception {
String jsonString = "{\n"
+ "\"items\": [{\n"
+ " \"id\": 633706061003,\n"
+ " \"fromNumber\": \"16572307534\",\n"
+ "\n"
+ " \"contact\": {\n"
+ " \"id\": 499354453003,\n"
+ " \"homePhone\": \"16572307534\"\n"
+ " },\n"
+ "\n"
+ " \"records\": [{\n"
+ " \"id\": 353389055003,\n"
+ " \"result\": \"LA\",\n"
+ " \"recordings\": [{\n"
+ " \"id\": 16427622003\n"
+ " }]\n"
+ " }]\n"
+ "}],\n"
+ "\"limit\": 100,\n"
+ "\"offset\": 0,\n"
+ "\"totalCount\": 5949\n"
+ "\n"
+ "}";
List keys1 = getKeysFromJson(jsonString);
System.out.println(keys1.size());
System.out.println(keys1);
}
static List getKeysFromJson(String jsoString) throws Exception {
Object things = new Gson().fromJson(jsoString, Object.class);
List keys = new ArrayList();
collectAllTheKeys(keys, things);
return keys;
}
static void collectAllTheKeys(List keys, Object o) {
Collection values = null;
if (o instanceof Map) {
Map map = (Map) o;
keys.addAll(map.keySet()); // collect keys at current level in hierarchy
values = map.values();
} else if (o instanceof Collection) {
values = (Collection) o;
} else{return;}
for (Object value : values) {
collectAllTheKeys(keys, value);
}
}
}
Output :
[items, limit, offset, totalCount, id, fromNumber, contact, records, id, homePhone, id, result, recordings, id]
Gson is one of the best ways to decode JSON file. Gson requires POJO classes, which can be manually generated but is tiresome. The best way to develop POJO classes is to visit jsonschema2pojo.org. They will generate the required POJO classes for you.
Let's say the class is JsonData.java
So in your code, you have to create a Gson object as well as an object of JsonData class.
String jsonFile = "____let this be your json data___"
Gson gson = new Gson();
JsonData jsonData = new JsonData();
jsonData = gson.fromJson(jsonFile, JsonData.class);
now jsonData will have all the data's retrieved from the json file. If you want to get fromNumber you can just call getFromNumber() which will be a method inside JsonData class. Similarly you can call other values too.
Try using third party services like jsonschema2pojo.org for improving your productivity.
I have following json which i need to convert into list of java objects.
{
"model":[
{
"syscall_1":"execve",
"syscall_2":"brk"
},
{
"syscall_1":"brk",
"syscall_2":"access"
},
{
"syscall_1":"access",
"syscall_2":"mmap"
},
{
"syscall_1":"mmap",
"syscall_2":"access"
}
]
}
I am using gson and its TypeToken>(){}.getType() API ,however I am bit confused about how my objects should look corresponding to input json.
How can I use TypeToken in this scenario?
Another option (not using the type token, but still achieves what you want) would be to parse the entire json object, then access the model array like so:
import com.google.gson.Gson;
import java.util.List;
public class TestMe {
public static void main(String[] args) {
String jsonSt2 = "{\"model\":[{\"syscall_1\":\"execve\",\"syscall_2\":\"brk\"},{\"syscall_1\":\"brk\",\"syscall_2\":\"access\"},{\"syscall_1\":\"access\",\"syscall_2\":\"mmap\"},{\"syscall_1\":\"mmap\",\"syscall_2\":\"access\"}]}";
System.out.println("your json: " + jsonSt2);
ModelObject object = new Gson().fromJson(jsonSt2, ModelObject.class);
System.out.println("Created Model object, array size is " + object.model.size());
for (ModelItem mi : object.model) {
System.out.println(mi.syscall_1 + " " + mi.syscall_2);
}
}
}
class ModelObject {
List<ModelItem> model;
}
class ModelItem {
String syscall_1;
String syscall_2;
}
Output
Created Model object, array size is 4
execve brk
brk access
access mmap
mmap access
mmap access
If you can use org.json to parse and construct list objects, you can try this.
String jsonSt2 = "{\"model\":[{\"syscall_1\":\"execve\",\"syscall_2\":\"brk\"},{\"syscall_1\":\"brk\",\"syscall_2\":\"access\"},{\"syscall_1\":\"access\",\"syscall_2\":\"mmap\"},{\"syscall_1\":\"mmap\",\"syscall_2\":\"access\"}]}";
List<Model> models = new ArrayList<>();
JSONObject jsonModelObject = new org.json.JSONObject(jsonSt2);
Object modelObject = jsonModelObject.get("model");
if (modelObject instanceof JSONArray) {
JSONArray itemsArray =(JSONArray) modelObject;
for (int index = 0; index < itemsArray.length(); index++) {
Model model = new Model();
JSONObject modelItereative = (JSONObject) itemsArray.get(index);
model.setSyscall_1(modelItereative.getString("syscall_1"));
model.setSyscall_2(modelItereative.getString("syscall_1"));
models.add(model);
}
}else if(modelObject instanceof JSONObject){
Model model = new Model();
JSONObject modelItereative = (JSONObject) modelObject;
model.setSyscall_1(modelItereative.getString("syscall_1"));
model.setSyscall_2(modelItereative.getString("syscall_1"));
models.add(model);
}
for(Model d22:models){
System.out.println(d22.getSyscall_1() + " " + d22.getSyscall_2());
}
I am using net.sf.json library and using it to parse my refMap like:
Map<String, Group> myMap = new HashMap<String,Group>();
myMap = this.getGroupValues();
JSONObject jsonObj = new JSONObject();
jsonObj.putAll(refMap);
File jsonFile = new File("./TempJson.txt");
FileWriter writer = new FileWriter(jsonFile);
fileWriter.write(jsonObj.toString());
where my Group class is defined as:
class Group {
Double val;
Integer num;
Section sectionObj;
//..getters & setters
}
The Problem is this.getGroupValues() returns some Group objects where val/num (wrapper classes) values are 'null' and then JsonObject parser converts it to 0 like: "val":0,"num":0
while if sectionObj is null , parser keeps it as null as "sectionObj":null
How to get null values for wrapper class Objects too in json file ?
I would suggest using a different JSON library. For example, GSON will leave null values out of the serialized JSON text. When it is deserialized by GSON, those missing values are set to null in the new object.
Consider this example:
public class Main {
public static void main(String[] args) {
Gson gson = new Gson();
final String json = gson.toJson(new Group());
System.out.println(json);
Group g = gson.fromJson(json, Group.class);
System.out.println(g);
}
public static class Group {
Double val;
Integer num;
Section sectionObj;
// Getters and setters...
#Override
public String toString() {
return "val: '" + val + "' num: '" + num
+ "' sectionObj: '" + sectionObj + "'";
}
}
public static class Section {}
}
which outputs the following:
{}
val: 'null' num: 'null' sectionObj: 'null'
I am fairly new to JSON parser and I am trying to extract all data set from "sizes" tag i.e extracting values (small, yes, xsmall, NO, Medium and yes) from the JSON file in a complex nested loop but doesn't work. I am using GSON to parse the JSON file and using JAVA as programming language
Here how the JSON file looks like in general
{ response: "ok",
prodinfo: {
sizes: [
{ size:"small",
available: "yes"
},
{ size:"xsmall",
available: "No"
},
{ size:"Medium",
available: "yes"
}
]
}
}
This is what i did
int array = jsonParser14.parse(json14).getAsJsonObject().get("ProdInfo").getAsJsonObject().getAsJsonArray("sizes").size();
JsonArray sizes = (JsonArray) jsonParser15.parse(json15).getAsJsonObject().get("ProdInfo").getAsJsonObject().getAsJsonArray("sizes");
for (int i = 0; i <= array; i++) {
String size = sizes.get(i).getAsString();
System.out.println("data extracted are: " + size);
}
Your help will be appreciated.
Thanks
I usually treat this by making a public class with required fields :
public class ProdSize {
public String size;
public String available;
}
public class ProdInfo {
public ProdSize[] sizes;
}
public class Message {
public String response;
public ProdInfo prodinfo;
}
And then I just have to do this in gson :
Gson gson = new GsonBuilder().create();
Message mess = gson.fromJson(theJsonString, Message.class);
Then, I don't have any loop to do to parse the JSON. I directly have my sizes in
mess.prodinfo.sizes
For example you can print them like this
for (int i=0; i<mess.prodinfo.sizes.length; i++) {
ProdSize size = mess.prodinfo.sizes[i];
System.out.println("Size " + size.size + " -> " + size.available);
}
Something like:
var sizes = json.prodinfo.sizes;
for (item in sizes) {
if (sizes.hasOwnProperty(item)) {
var isAvailable = sizes[item].available;
alert(isAvailable);
}
}
Example here: http://jsfiddle.net/nG88B/3/
Edit:
Looks like you need to parse the JSON first. In which case (if it's valid) you can do:
var obj = JSON.parse(jsonStr);