I need to serialize simple java object with three fields (one is a List of objects) into json to look something like this:
{
"id": "1",
"fields": [
{
"value": {
"someNumber": "0.0.2"
},
"id": "67"
}
],
"name": "Daniel"}
I've read guides on custom serializers StdSerializer and JsonGenerator, as i undestood, to write "name": "Daniel" into json you need to do somwthing like gen.writeObjectField("name", name); but i cannot get my head on two things:
How to write some string value like here:
"value": {
"name": "0.0.2"
},
And how to write java List as an array like this:
"fields": [
{
"value": {
"someNumber": "0.0.2"
},
"id": "67"
}]
where "fields" is an List full of objects having two fields: "value" and "id".
Any help is appreciated
like this
public class Test {
public static void main(String[] args) throws IOException {
String ret;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectMapper mapper = new ObjectMapper();
JsonGenerator jg = mapper.getJsonFactory().createJsonGenerator(new PrintWriter(bos));
jg.writeStartObject();
jg.writeStringField("id", "1");
jg.writeArrayFieldStart("fields");
jg.writeStartObject();
jg.writeObjectFieldStart("value");
jg.writeStringField("someNumber","0.0.2");
jg.writeEndObject();
jg.writeStringField("id","67");
jg.writeEndObject();
//you can write more objects in fields here
jg.writeEndArray();
jg.writeStringField("name","Daniel");
jg.writeEndObject();
jg.flush();
jg.close();
ret = bos.toString();
bos.close();
System.out.println(ret);
}
}
and the result is
{
"id":"1",
"fields":[
{
"value":{
"someNumber":"0.0.2"
},
"id":"67"
}
],
"name":"Daniel"
}
Related
I have data that looks like this:
{
"status": "success",
"data": {
"irrelevant": {
"serialNumber": "XYZ",
"version": "4.6"
},
"data": {
"lib": {
"files": [
"data1",
"data2",
"data3",
"data4"
],
"another file": [
"file.jar",
"lib.jar"
],
"dirs": []
},
"jvm": {
"maxHeap": 10,
"maxPermSize": "12"
},
"serverId": "134",
"version": "2.3"
}
}
}
Here is the function I'm using to prettify the JSON data:
public static String stringify(Object o, int space) {
ObjectMapper mapper = new ObjectMapper();
try {
return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(o);
} catch (Exception e) {
return null;
}
}
I am using the Jackson JSON Processor to format JSON data into a String.
For some reason the JSON format is not in the format that I need. When passing the data to that function, the format I'm getting is this:
{
"status": "success",
"data": {
"irrelevant": {
"serialNumber": "XYZ",
"version": "4.6"
},
"another data": {
"lib": {
"files": [ "data1", "data2", "data3", "data4" ],
"another file": [ "file.jar", "lib.jar" ],
"dirs": []
},
"jvm": {
"maxHeap": 10,
"maxPermSize": "12"
},
"serverId": "134",
"version": "2.3"
}
}
}
As you can see under the "another data" object, the arrays are displayed as one whole line instead of a new line for each item in the array. I'm not sure how to modify my stringify function for it to format the JSON data correctly.
You should check how DefaultPrettyPrinter looks like. Really interesting in this class is the _arrayIndenter property. The default value for this property is FixedSpaceIndenter class. You should change it with Lf2SpacesIndenter class.
Your method should looks like this:
public static String stringify(Object o) {
try {
ObjectMapper mapper = new ObjectMapper();
DefaultPrettyPrinter printer = new DefaultPrettyPrinter();
printer.indentArraysWith(new Lf2SpacesIndenter());
return mapper.writer(printer).writeValueAsString(o);
} catch (Exception e) {
return null;
}
}
I don't have enough reputation to add the comment, but referring to the above answer Lf2SpacesIndenter is removed from the newer Jackson's API (2.7 and up), so instead use:
printer.indentArraysWith(DefaultIndenter.SYSTEM_LINEFEED_INSTANCE);
Source of the solution
I am consuming an external web service and receiving a JSON response. In this response, there is an object "entities" containing multiple arrays in it, with a name before each array.
I want to add the name before the array in the array object itself.
For example this is the original response:
{
"entities": {
"entity": [
{
"confidence": 1,
"value": "user",
"type": "value"
},
{
"confidence": 1,
"value": "insurance form",
"type": "value"
}
],
"ui_page_step": [
{
"confidence": 1,
"value": "step 1",
"type": "value"
}
],
"userrole_ano": [
{
"confidence": 0.96535832252792,
"value": "anonymous user"
}
]
}
}
I need to convert it to:
{
"entities": {
"entity": [
{
"name": "entity",
"confidence": 1,
"value": "user",
"type": "value"
},
{
"name": "entity",
"confidence": 1,
"value": "insurance form",
"type": "value"
}
],
"ui_page_step": [
{
"name": "ui_page_step",
"confidence": 1,
"value": "step 1",
"type": "value"
}
],
"userrole_ano": [
{
"name": "userrole_ano",
"confidence": 0.96535832252792,
"value": "anonymous user"
}
]
}
}
How can I convert the original response to the desired one in Java?
Here is a (one of several possible) solutions:
It uses Jackson library to parse the Json into a java Map that is (relatively) easier to navigate and modify than JSONObject.
the method putCollectionNamesInsideEntries() assumes one root "entities" entry that has several collections as values. it iterates over all of them, adding "name" entry with name of collection.
the map is serialized back to Json (and sent to System.out)
import java.io.*;
import java.nio.file.*;
import java.util.*;
import com.fasterxml.jackson.databind.ObjectMapper;
public class JacksonTest
{
public static void main(String[] args) {
try (InputStream is = Files.newInputStream(Paths.get("C:/temp/test.json"))) {
ObjectMapper mapper = new ObjectMapper();
// deserialize json into map
Map<String, Object> map = (Map<String, Object>)mapper.readValue(is, Map.class);
putCollectionNamesInsideEntries(map);
// serialize map into json
mapper.writeValue(System.out, map);
} catch (Exception e) {
e.printStackTrace();
}
}
private static void putCollectionNamesInsideEntries(Map<String, Object> map) {
// get root "entities" entry
Map<String, Object> entitiesMap = (Map<String, Object>)map.get("entities");
for (Map.Entry<String, Object> entitiesEntry : entitiesMap.entrySet()) {
// iterate over collection entries
if (entitiesEntry.getValue() instanceof Collection) {
Collection coll = (Collection)entitiesEntry.getValue();
// iterate over entries in collection
for (Object collEntry : coll) {
if (collEntry instanceof Map) {
// add "name" with ame of collection (key entry under "entries")
((Map<String, Object>)collEntry).put("name", entitiesEntry.getKey());
}
}
}
}
}
}
I am very new to json, How can I make a JSON object the structure (output string)would be like this? I am using the org.json library.
Is this a json array contians json array?
I have input like this:
111(root)
----222(child of 111)
--------333(child of 222)
--------444(child of 222)
----123(child of 111)
--------456(child of 123)
--------456(child of 123)
How can I make a json the output would be like blow,
{
"name": "flare",
"children": [
{
"name": "analytics",
"children": [
{
"name": "cluster",
"children": [
{
"name": "AgglomerativeCluster",
"value": 3938
},
{
"name": "CommunityStructure",
"value": 3812
}
]
},
{
"name": "graph",
"children": [
{
"name": "BetweennessCentrality",
"value": 3534
},
{
"name": "LinkDistance",
"value": 5731
}
]
}
]
},
{
"name": "animate",
"children": [
{
"name": "Easing",
"value": 17010
},
{
"name": "FunctionSequence",
"value": 5842
}
]
}
]
}
Thanks for you help!
You can change your dependency and use a library that allows Object mapping such as Jackson, or you can do the mapping by hand as follows:
private static JSONObject toJSONObject(String name, Object value) {
JSONObject ret = new JSONObject();
ret.put("name", name);
if (value != null) {
ret.put("value", value);
}
return ret;
}
public static JSONObject addChildren(JSONObject parent, JSONObject... children) {
parent.put("children", Arrays.asList(children));
return parent;
}
public static void main(String[] sargs) {
JSONObject flare = toJSONObject("flare", null);
addChildren(flare,
addChildren(toJSONObject("analytics", null),
addChildren(toJSONObject("cluster", null),
toJSONObject("AgglomerativeCluster", 3938),
toJSONObject("CommunityStructure", 3812)
),
addChildren(toJSONObject("graph", null),
toJSONObject("BetweennessCentrality", 3534),
toJSONObject("LinkDistance", 5731)
)
),
addChildren(toJSONObject("animate", null),
toJSONObject("Easing", 17010),
toJSONObject("FunctionSequence", 5842)
)
);
System.out.println(flare.toString());
}
You can simply have class like this.
public class Node {
String name;
List<Node> children;
String value;
}
This can be achieved by ObjectMapper's pretty print.
public String pretty(Object object) throws JsonProcessingException {
return OBJECT_MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(object);
}
You may use my library for it.
<dependency>
<artifactId>json-utils</artifactId>
<groupId>org.bitbucket.swattu</groupId>
<version>1.0.16</version>
</dependency>
new JsonUtil().pretty(object);
{"myContainer" :
{ "couldBeAnything" : [
{"id":1, "name":"sb", "category":"couldBeAnything"},
{"id":2, "name":"bs", "category":"couldBeAnything"}
],
"somethingElse" : [
{"id":1, "name":"sdsa","category":"somethingElse"},
{"id":2, "name":"ve","category":"somethingElse"}
]
},
"id" : 0
}
So far I have :
Type myContainerType = new TypeToken<MyContainer>(){}.getType();
MyContainerType myContainerType = gson.fromJson(myJson.getValue(), myContainerType);
Where
public class MyContainer {
private int id;
private Map<String, List<Foo>> foo; // and foo has id, name, category
The result, no errors, a populated id field, but just a null map
I think the json is wrong for the structure Map<String, List<Foo>>. When you say map you need not enclose each key-value with {. Just put the whole key values in one {} and seprate with commas. eg
{
"myContainer": {
"couldBeAnything": [
{
"id": 1,
"name": "sb",
"category": "couldBeAnything"
},
{
"id": 2,
"name": "bs",
"category": "couldBeAnything"
}
],
"somethingElse": [
{
"id": 1,
"name": "sdsa",
"category": "somethingElse"
},
{
"id": 2,
"name": "ve",
"category": "somethingElse"
}
]
},
"id": 0
}
With this json it works perfectly
public static void main(String[] args){
String json = "{\"myContainer\":{\"couldBeAnything\":[{\"id\":1,\"name\":\"sb\",\"category\":\"couldBeAnything\"},{\"id\":2,\"name\":\"bs\",\"category\":\"couldBeAnything\"}],\"somethingElse\":[{\"id\":1,\"name\":\"sdsa\",\"category\":\"somethingElse\"},{\"id\":2,\"name\":\"ve\",\"category\":\"somethingElse\"}]},\"id\":0}";
Map<String, List<Foo>> obj = new HashMap<String, List<Foo>>();
Gson gson = new Gson();
obj = gson.fromJson(json, obj.getClass());
System.out.println(obj);
}
Output
{id=0.0, myContainer={couldBeAnything=[{id=1.0, name=sb, category=couldBeAnything}, {id=2.0, name=bs, category=couldBeAnything}], somethingElse=[{id=1.0, name=sdsa, category=somethingElse}, {id=2.0, name=ve, category=somethingElse}]}}
The issue with your approach was the naming of the field foo. Your json contains the Map<String, List<Foo>> name as myContainer. So modify your container class like below and it will work fine :)
public class MyContainer {
private int id;
private Map<String, List<Foo>> myContainer;
}
Now this will work
Type myContainerType = new TypeToken<MyContainer>(){}.getType();
MyContainer myContainer = gson.fromJson(json, myContainerType);
System.out.println(myContainer);
Can somebody help me with Gson parser. When I remove change from JSON and Result it works fine but with change it throws JsonParseException-Parse failed.
Result[] response = gson.fromJson(fileData.toString(), Result[].class);
I have classes like this
public class Result {
public String start_time;
public String end_time;
public change[] change;
}
and
public class change {
public String id;
public String name;
}
and Json string like
[
{
"start_time": "8:00",
"end_time": "10:00",
"change": [
{
"id": "1",
"name": "Sam"
},
{
"id": "2",
"name": "John"
}
]
},
{
"start_time": "9:00",
"end_time": "15:00",
"change": [
{
"id": "1",
"name": "Sam"
},
{
"id": "2",
"name": "John"
}
]
}
]
Can somebody tell me what I did wrong ? Any idea why it won't work with array ?
As has been suggested, you need to use a list instead. Gson has pretty good documentation for using parametized types with the parser, you can read more about it here. Your code will end up looking like this:
Type listType = new TypeToken<List<Result>>() {}.getType();
List<Result> results = gson.fromJson(reader, listType);
for (Result r : results) {
System.out.println(r);
}