Difference between '{' and '[' when formatting JSON object - json

Is there any difference between '{' and '[' when formatting a JSON object?

Yep one {...} is used to define a single object, while the other [...] is used to define a sequence of either objects, values or lists ...
objects are defined as such {key:object or list or value , ...}
list ares nothing more than a sequence of either objects or lists or values, [objects or list or values, ... ]...
[{'value':1}, {'values':[1,2,3,3, {'a':'a', 'b':'b'}]}, 2, 3, 4]

'{ } ' used for Object and '[]' is used for Array in json
Like
var sampleObj = {
a:1,
b:'ab'
};
var sampleArr = [1,'ab',4];

They don't have the same meaning at all. {} denote containers, [] denote arrays.

package ravi.kumar;
import java.util.ArrayList;
import java.lang.Object;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class SetListClass {
public static void main(String[] args) {
SetListClass SetListClass = new SetListClass();
List<String> list = new ArrayList<String>();
list.add("country");
list.add("state");
list.add("distract");
list.add("country");
System.out.println(list);
System.out.println("----------------------------------------------");
SetListClass.getset();
System.out.println("----------------------------------------------");
SetListClass.getHashMap();
}
public void getset()
{
Set<String> set = new HashSet<String>();
set.add("country");
set.add("state");
set.add("distract");
set.add("country");
System.out.println(set);
System.out.println(set.remove("country"));
System.out.println("---------------------------------------------");
System.out.println(set);
}
public void getHashMap() {
HashMap<String, Object> hashmap = new HashMap<String, Object>();
hashmap.put("country", "india");
hashmap.put("state", "bihar");
hashmap.put("district", "buxar");
System.out.println(hashmap);
}
}
output
-------
[country, state, distract, country] ------array
----------------------------------------------
[state, distract, country] ----array
true
---------------------------------------------
[state, distract]
----------------------------------------------
{state=bihar, district=buxar, country=india} ---Object

Related

Show JSON in TableView

I am developing a generic editor for JSON Array using JavaFX.
The display in the table in such a way that the columns will be the keys, and the value in the rows will be more descriptive. There can be a different number of keys in one JSONObject.
JSON of the form:
"[{\"key1\": 1, \"key2\": 2}, {\"key1\": 3, \"key2\": 4}]"
It needs to look like this:
key1
key2
1
2
3
4
Have any suggestions?
This can be broken down into two parts.
Use GSON to parse a JSON Array to an Array of POJOs.
Display a List of Objets in a TableView.
Key Code
//Add data to the TableView!
String jsonString = "[{\"keyOne\":\"1\", \"keyTwo\":\"2\"}, {\"keyOne\":\"3\", \"keyTwo\":\"4\"}]";
Gson gson = new Gson();
Data[] dataList = gson.fromJson(jsonString, Data[].class);
ObservableList<Data> observableList = FXCollections.observableArrayList(dataList);
tableView.setItems(observableList);
Main
import com.google.gson.Gson;
import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.stage.Stage;
import javafx.scene.layout.StackPane;
public class App extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage){
TableView<Data> tableView = new TableView();
TableColumn<Data, String> column1 = new TableColumn<>("Key One");
column1.setCellValueFactory((cdf) -> new SimpleStringProperty(cdf.getValue().getKeyOne()));
TableColumn<Data, String> column2 = new TableColumn<>("Key Two");
column2.setCellValueFactory((cdf) -> new SimpleStringProperty(cdf.getValue().getKeyTwo()));
tableView.getColumns().add(column1);
tableView.getColumns().add(column2);
//Add data to the TableView!
String jsonString = "[{\"keyOne\":\"1\", \"keyTwo\":\"2\"}, {\"keyOne\":\"3\", \"keyTwo\":\"4\"}]";
Gson gson = new Gson();
Data[] dataList = gson.fromJson(jsonString, Data[].class);
ObservableList<Data> observableList = FXCollections.observableArrayList(dataList);
tableView.setItems(observableList);
Scene scene = new Scene(new StackPane(tableView));
stage.setTitle("JavaFX 13");
stage.setScene(scene);
stage.show();
}
}
Data Class
/**
*
* #author sedj601
*/
public class Data {
private String keyOne;
private String keyTwo;
public Data(String keyOne, String keyTwo) {
this.keyOne = keyOne;
this.keyTwo = keyTwo;
}
public String getKeyOne() {
return keyOne;
}
public void setKeyOne(String keyOne) {
this.keyOne = keyOne;
}
public String getKeyTwo() {
return keyTwo;
}
public void setKeyTwo(String keyTwo) {
this.keyTwo = keyTwo;
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("Data{keyOne=").append(keyOne);
sb.append(", keyTwo=").append(keyTwo);
sb.append('}');
return sb.toString();
}
}
module-info.java
module com.mycompany.javafx_test_2 {
requires javafx.controls;
exports com.mycompany.javafx_test_2;
opens com.mycompany.javafx_test_2 to com.google.gson;
requires com.google.gson;
}
Using GSON version 2.8.9.
Output

How to parse JSON's array of numbers

I'm facing the following situation parsing a JSON.
The JSON I want to unmarshal contains an array of numbers (doubles) like this:
"position":[52.50325,13.39062]
So there is no name/value pairs.
The Problem is that I can't get the value of this array. In the Java object modeling the JSON I defined the position attribute as list of Doubles: List<Double> but after the unmarshel, the position attribute is always null.
For testing purpose I changed the content of the JSON like that:
position: [„52.50325“ ,“ 13.39062“ ]
and then there is no issue, I get the list with two elements. (Btw, this happens regardless if the position is defined as list of Strings or list of Doubles (List<String> or List<Double>))
So a workaround could be to alter the JSON response and mark this numbers as string before unmarshaling it, but I would like to avoid that, and I’m wondering if there is solution to get the value of a number array?
Here is a snapshot from the code:
ResultsListDO.java:
#XmlElement(required = true)
protected List<Double> position;
public List<Double> getPosition()
{
if (position == null) {
position = new ArrayList<Double>();
}
return this.position;
}
JSON unmarshal:
context = new JSONJAXBContext(JSONConfiguration.mapped().build(), ResultsListDO.class);
JSONUnmarshaller um = context.createJSONUnmarshaller();
ResultsListDO resultsList = um.unmarshalFromJSON(source.getReader(), ResultsListDO.class);
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
Unless you have annotated your class with #XmlAccessorType(XmlAccessType.FIELD) the problem is probably that your annotation is on the field rather than the get method (see: http://blog.bdoughan.com/2011/06/using-jaxbs-xmlaccessortype-to.html).
import java.util.*;
import javax.xml.bind.annotation.XmlElement;
public class Foo {
protected List<Double> position;
#XmlElement(required = true)
public List<Double> getPosition()
{
if (position == null) {
position = new ArrayList<Double>();
}
return this.position;
}
}
Demo Code
Below I'll demonstrate that everything works using MOXy as the JSON-binding provider.
jaxb.properties
To specify MOXy as your JAXB provider you need to include a file called jaxb.properties in the same package as your domain model with the following entry (see: http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html).
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
Demo
import java.util.*;
import javax.xml.bind.*;
import javax.xml.transform.stream.StreamSource;
import org.eclipse.persistence.jaxb.JAXBContextProperties;
public class Demo {
public static void main(String[] args) throws Exception {
Map<String, Object> properties = new HashMap<String,Object>();
properties.put(JAXBContextProperties.MEDIA_TYPE, "application/json");
properties.put(JAXBContextProperties.JSON_INCLUDE_ROOT, false);
JAXBContext jc = JAXBContext.newInstance(new Class[] {Foo.class}, properties);
Unmarshaller unmarshaller = jc.createUnmarshaller();
StreamSource json = new StreamSource("src/forum18355753/input.json");
Foo foo = unmarshaller.unmarshal(json, Foo.class).getValue();
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(foo, System.out);
}
}
input.json/Output
{
"position" : [ 52.50325, 13.39062 ]
}

JSON to String with inner array convertion

I have a larga data JSON which I want to pass to the backend to be parsed there to become into java objects.
To make this I'm using the JSON.stringify function but inside the JSON there is an array attribute that the JSON.stringify is enclosing between quotes ("), so when Gson find it (the way I'm using at the backend to decode the string into objects), it throws an error because this is not an array inside a JSON string representation, but an string attibute inside a JSON string representation.
This is an example of the string generated with JSON.stringify:
{"id":0, "array": "[{\"id\":0, \"cod\": \"XXX\"}, {\"id\":0, \"cod\": \"XXX\"}]"}
The array attribute cannot be converted by Gson because is not an array.
Can anybody help me with this issue?
Thanks a lot.
I'd likely prefer to fix the generated JSON, but if that's not possible or otherwise preferable, it looks like you'll simply need to deserialize part of the JSON twice. This could be accomplished with a custom deserializer as follows.
import java.lang.reflect.Type;
import java.util.Arrays;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
public class GsonFoo
{
public static void main(String[] args)
{
// With the generated JSON corrected:
// {"id":42, "array": [{"id":1, "cod": "aaa"}, {"id":2, "cod": "bbb"}]}
String jsonInput = "{\"id\":42, \"array\": [{\"id\":1, \"cod\": \"aaa\"}, {\"id\":2, \"cod\": \"bbb\"}]}";
Gson gson = new Gson();
Bar bar1 = gson.fromJson(jsonInput, Bar.class);
System.out.println(bar1);
// Bar: id=42, array=[Thing: id=1, cod=aaa, Thing: id=2, cod=bbb]
// -------------------------
// With the funky JSON:
// {"id":42, "array": "[{\"id\":1, \"cod\": \"aaa\"}, {\"id\":2, \"cod\": \"bbb\"}]"}
String funkyJsonInput = "{\"id\":42, \"array\": \"[{\\\"id\\\":1, \\\"cod\\\": \\\"aaa\\\"}, {\\\"id\\\":2, \\\"cod\\\": \\\"bbb\\\"}]\"}";
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Thing[].class, new FunkyThingArrayDeserializer());
gson = gsonBuilder.create();
Bar bar2 = gson.fromJson(funkyJsonInput, Bar.class);
System.out.println(bar2);
// Bar: id=42, array=[Thing: id=1, cod=aaa, Thing: id=2, cod=bbb]
}
}
class FunkyThingArrayDeserializer implements JsonDeserializer<Thing[]>
{
#Override
public Thing[] deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException
{
String actualJson = context.deserialize(json, String.class);
return new Gson().fromJson(actualJson, Thing[].class);
}
}
class Bar
{
int id;
Thing[] array;
#Override
public String toString()
{
return String.format("Bar: id=%d, array=%s", id, Arrays.toString(array));
}
}
class Thing
{
int id;
String cod;
#Override
public String toString()
{
return String.format("Thing: id=%d, cod=%s", id, cod);
}
}
You need to write this code before invoke JSON.stringify
if(window.Prototype) {
delete Object.prototype.toJSON;
delete Array.prototype.toJSON;
delete Hash.prototype.toJSON;
delete String.prototype.toJSON;
}

Jackson complex list serialization

I'm experementing with Jackson serialization/deserialization.
For instance, I have such class:
class Base{
String baseId;
}
And I want to serialize List objs;
To do it with jackson, I need to specify a list's elements real type, due to the java type erasure.
This code will work:
List<Base> data = getData();
return new ObjectMapper().writerWithType(TypeFactory.collectionType(List.class, Base.class)).writeValueAsString(data);
Now, I want to serialize more complex class:
class Result{
List<Base> data;
}
How should I tell Jackson to properly serialize this class?
Just
new ObjectMapper().writeValueAsString(myResult);
The type of the list won't be lost due to type erasure in the same way it would be in the first example.
Note that for vanilla serialization of a list or generic list, it's not necessary to specify the list component types, as demonstrated in the example in the original question. All three of the following example serializations represent the List<Bar> with the exact same JSON.
import java.util.ArrayList;
import java.util.List;
import org.codehaus.jackson.annotate.JsonAutoDetect.Visibility;
import org.codehaus.jackson.annotate.JsonMethod;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.ObjectWriter;
public class JacksonFoo
{
public static void main(String[] args) throws Exception
{
Baz baz = new Baz("BAZ", 42);
Zab zab = new Zab("ZAB", true);
List<Bar> bars = new ArrayList<Bar>();
bars.add(baz);
bars.add(zab);
ObjectMapper mapper = new ObjectMapper().setVisibility(JsonMethod.FIELD, Visibility.ANY);
String json1 = mapper.writeValueAsString(bars);
System.out.println(json1);
// output:
// [{"name":"BAZ","size":42},{"name":"ZAB","hungry":true}]
Foo foo = new Foo(bars);
String json2 = mapper.writeValueAsString(foo);
System.out.println(json2);
// output:
// {"bars":[{"name":"BAZ","size":42},{"name":"ZAB","hungry":true}]}
mapper = new ObjectMapper().setVisibility(JsonMethod.FIELD, Visibility.ANY);
ObjectWriter typedWriter = mapper.writerWithType(mapper.getTypeFactory().constructCollectionType(List.class, Bar.class));
String json3 = typedWriter.writeValueAsString(bars);
System.out.println(json3);
// output:
// [{"name":"BAZ","size":42},{"name":"ZAB","hungry":true}]
}
}
class Foo
{
List<Bar> bars;
Foo(List<Bar> b) {bars = b;}
}
abstract class Bar
{
String name;
Bar(String n) {name = n;}
}
class Baz extends Bar
{
int size;
Baz(String n, int s) {super(n); size = s;}
}
class Zab extends Bar
{
boolean hungry;
Zab(String n, boolean h) {super(n); hungry = h;}
}
A typed writer is useful when serializing with additional type information. Note how the json1 and json3 outputs below differ.
import java.util.ArrayList;
import java.util.List;
import org.codehaus.jackson.annotate.JsonAutoDetect.Visibility;
import org.codehaus.jackson.annotate.JsonMethod;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.ObjectMapper.DefaultTyping;
import org.codehaus.jackson.map.ObjectWriter;
public class JacksonFoo
{
public static void main(String[] args) throws Exception
{
Baz baz = new Baz("BAZ", 42);
Zab zab = new Zab("ZAB", true);
List<Bar> bars = new ArrayList<Bar>();
bars.add(baz);
bars.add(zab);
ObjectMapper mapper = new ObjectMapper().setVisibility(JsonMethod.FIELD, Visibility.ANY);
mapper.enableDefaultTypingAsProperty(DefaultTyping.OBJECT_AND_NON_CONCRETE, "type");
String json1 = mapper.writeValueAsString(bars);
System.out.println(json1);
// output:
// [
// {"type":"com.stackoverflow.q8416904.Baz","name":"BAZ","size":42},
// {"type":"com.stackoverflow.q8416904.Zab","name":"ZAB","hungry":true}
// ]
Foo foo = new Foo(bars);
String json2 = mapper.writeValueAsString(foo);
System.out.println(json2);
// output:
// {
// "bars":
// [
// "java.util.ArrayList",
// [
// {"type":"com.stackoverflow.q8416904.Baz","name":"BAZ","size":42},
// {"type":"com.stackoverflow.q8416904.Zab","name":"ZAB","hungry":true}
// ]
// ]
// }
mapper = new ObjectMapper().setVisibility(JsonMethod.FIELD, Visibility.ANY);
mapper.enableDefaultTypingAsProperty(DefaultTyping.OBJECT_AND_NON_CONCRETE, "type");
ObjectWriter typedWriter = mapper.writerWithType(mapper.getTypeFactory().constructCollectionType(List.class, Bar.class));
String json3 = typedWriter.writeValueAsString(bars);
System.out.println(json3);
// output:
// [
// "java.util.ArrayList",
// [
// {"type":"com.stackoverflow.q8416904.Baz","name":"BAZ","size":42},
// {"type":"com.stackoverflow.q8416904.Zab","name":"ZAB","hungry":true}
// ]
// ]
}
}

Global property filter in Jackson

Is there a way to register a global property filter in ObjectMapper?
Global means that it will be applied to all serialized beans. I can't use annotations (I can't modify serialized beans) and don't know what properties the beans have.
The filtering should be name based.
My first idea was to write a custom serializer, but I don't know what should I pass to the constructor.
I'd make use of a FilterProvider. It's a little involved, but not too unwieldy.
import org.codehaus.jackson.annotate.JsonAutoDetect.Visibility;
import org.codehaus.jackson.annotate.JsonMethod;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.ObjectWriter;
import org.codehaus.jackson.map.annotate.JsonFilter;
import org.codehaus.jackson.map.ser.FilterProvider;
import org.codehaus.jackson.map.ser.impl.SimpleBeanPropertyFilter;
import org.codehaus.jackson.map.ser.impl.SimpleFilterProvider;
public class JacksonFoo
{
public static void main(String[] args) throws Exception
{
Bar bar = new Bar();
bar.id = "42";
bar.name = "James";
bar.color = "blue";
bar.foo = new Foo();
bar.foo.id = "7";
bar.foo.size = "big";
bar.foo.height = "tall";
ObjectMapper mapper = new ObjectMapper().setVisibility(JsonMethod.FIELD, Visibility.ANY);
System.out.println(mapper.writeValueAsString(bar));
// output:
// {"id":"42","name":"James","color":"blue","foo":{"id":"7","size":"big","height":"tall"}}
String[] ignorableFieldNames = { "id", "color" };
FilterProvider filters = new SimpleFilterProvider().addFilter("filter properties by name", SimpleBeanPropertyFilter.serializeAllExcept(ignorableFieldNames));
mapper = new ObjectMapper().setVisibility(JsonMethod.FIELD, Visibility.ANY);
mapper.getSerializationConfig().addMixInAnnotations(Object.class, PropertyFilterMixIn.class);
ObjectWriter writer = mapper.writer(filters);
System.out.println(writer.writeValueAsString(bar));
// output:
// {"name":"James","foo":{"size":"big","height":"tall"}}
}
}
#JsonFilter("filter properties by name")
class PropertyFilterMixIn
{
}
class Bar
{
String id;
String name;
String color;
Foo foo;
}
class Foo
{
String id;
String size;
String height;
}
For other approaches and more information, I recommend the following resources.
http://wiki.fasterxml.com/JacksonJsonViews
http://www.cowtowncoder.com/blog/archives/2011/02/entry_443.html
http://wiki.fasterxml.com/JacksonFeatureJsonFilter
http://www.cowtowncoder.com/blog/archives/2011/09/entry_461.html