I currently use handlebars in java (com.github.jknack.handlebars)
and have a handlebars helper method to get a link (with some logic behind)
{{ getLink data.node}}
which just render the url /subfolder/link.html
In my handlebars template I now only want to print the url (a-tag) when the helper method returns a non empty string (e.g. there is a link available)
I tried it with
{{#if getLink data.node }}
Link-Text
{{/if}}
but no link was rendered
What would be the correct syntax for my if?
Thanks
RCX
Edit:
getLink Helper Method in LinkHelper.class
public CharSequence getLink(JsonObject node, Options options) throws IOException {
String link = fetchLink(node);
if(link != null){
return link;
}
return "";
}
registered via
HandlebarsTemplateEngineImpl.getHandlebars().registerHelpers(new LinkHelper());
Handlebars.java is not well documented and missing couple of unit tests (consider to contribute if this answer helped), for some reason calling nested JsonObject removed at this commit, you can still call nested String, but there is a trick with parentheses.
Full example:
import com.github.jknack.handlebars.Context;
import com.github.jknack.handlebars.Handlebars;
import com.github.jknack.handlebars.Helper;
import com.github.jknack.handlebars.Template;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.Map;
public class HandlebarsJavaTest {
public static void main(String[] args) throws IOException {
Handlebars handlebars = new Handlebars();
Gson gson = new Gson();
handlebars.registerHelper("getLink", (Helper<Map<String, Object>>) (jsonObject, options) -> {
String link = fetchLink(jsonObject);
return link != null ? link : "";
});
String data = "{'data':{'node':'/bla.html', 'node2':'inside node2'}}";
// Pay attention to parentheses !!!
// {{#if (getLink data.node)}} throws ClassCastException, java.lang.String cannot be cast to java.util.Map
String rawTemplate = "{{#if (getLink data)}} Link-Text {{/if}}";
Type type = new TypeToken<Map<String, Object>>(){}.getType();
Map<String, Object> map = gson.fromJson(data, type);
Template template = handlebars.compileInline(rawTemplate);
Context context = Context.newBuilder(map).build();
System.out.println(template.apply(context));
}
private static String fetchLink(Map<String, Object> map) {
try {
return map.get("node").toString();
} catch (NullPointerException npe) {
return null;
}
}
}
Output:
Link-Text
If node is just a string ( same output )
public static void main(String[] args) throws IOException {
Handlebars handlebars = new Handlebars();
Gson gson = new Gson();
handlebars.registerHelper("getLink", (Helper<String>) (node, options) -> node != null ? node : "");
String data = "{'data':{'node':'/bla.html', 'node2':'inside node2'}}";
// Pay attention to parentheses !!!
String rawTemplate = "{{#if (getLink data.node)}} Link-Text {{/if}}";
Type type = new TypeToken<Map<String, Object>>(){}.getType();
Map<String, Object> map = gson.fromJson(data, type);
Template template = handlebars.compileInline(rawTemplate);
Context context = Context.newBuilder(map).build();
System.out.println(template.apply(context));
}
If you insist node is an object using this.[data] or this.[data.node] will not do the work, working example for the same output:
import com.github.jknack.handlebars.Context;
import com.github.jknack.handlebars.Handlebars;
import com.github.jknack.handlebars.Helper;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
public class HandlebarsJavaTest {
public static void main(String[] args) throws Exception {
System.out.println(
new Handlebars()
.registerHelper("getLink", (Helper<JsonObject>) (json, options) -> {
try {
// logic here
return json.get("data").getAsJsonObject().get("node").getAsJsonObject().get("link").getAsString();
} catch (NullPointerException npe) {
return null;
}
})
// Pay attention to parentheses !!
.compileInline("{{#if (getLink this) }} Link-Text {{/if}}")
.apply(
Context
.newBuilder(
new Gson()
.fromJson(
"{ 'data': { 'node': { 'link': '/bla.html' }, 'node2': 'inside node2' } }",
JsonObject.class
)
).build()
)
);
}
}
If you have time, consider to contribute to this open source by adding proper documentation or at least unit tests {{#if (method param)}}.
According to the source code
package com.github.jknack.handlebars;
public class IfBlockTest extends AbstractTest {
#Test
public void falsy() throws IOException {
// empty string
shouldCompileTo("{{#if value}}true{{else}}false{{/if}}", $("value", ""), "false");
BTW, the #if built-in helper will return False for empty string, so if getLink will execute return ""; the if condition will not and the text will not be rendered, to assert this you can add {{else}} before the closing if {{/if}} and see that what is rendered.
Related
I download the following JSON using the Wikipedia-Api:
["aa",
["Aarhus","Aalen","Aalborg","Aargau","Aare"],
["","","","",""],
["https://wiki.openstreetmap.org/wiki/Aarhus",
"https://wiki.openstreetmap.org/wiki/Aalen",
"https://wiki.openstreetmap.org/wiki/Aalborg",
"https://wiki.openstreetmap.org/wiki/Aargau",
"https://wiki.openstreetmap.org/wiki/Aare"
]
]
Several online JSON validators accept this format without warning or even errors.
This JSON is rejected by my program:
class OsmWikiResult {
private String start;
private String[] file;
private String[] dummy;
private String[] link;
}
... snip ...
Gson gson = new Gson();
OsmWikiResult owr = gson.fromJson(inputLine, OsmWikiResult.class);
inputLine is containing the whole JSON in one line.
java -jar target/OsmWiki-1.0-jar-with-dependencies.jar xxxx
OsmWiki
getListFromOsmWiki() starting.
Url: https://wiki.openstreetmap.org/w/api.php?action=opensearch&search=aa&limit=500&namespace=0&format=json
["aa",["Aarhus","Aalen","Aalborg","Aargau","Aare"],["","","","",""],["https://wiki.openstreetmap.org/wiki/Aarhus","https://wiki.openstreetmap.org/wiki/Aalen","https://wiki.openstreetmap.org/wiki/Aalborg","https://wiki.openstreetmap.org/wiki/Aargau","https://wiki.openstreetmap.org/wiki/Aare"]]
Exception in thread "main" com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2 path $
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:224)
at com.google.gson.Gson.fromJson(Gson.java:888)
at com.google.gson.Gson.fromJson(Gson.java:853)
at com.google.gson.Gson.fromJson(Gson.java:802)
at com.google.gson.Gson.fromJson(Gson.java:774)
at com.wno.OsmWiki.getListFromOsmWiki(OsmWiki.java:80)
at com.wno.OsmWiki.main(OsmWiki.java:114)
Caused by: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2 path $
at com.google.gson.stream.JsonReader.beginObject(JsonReader.java:385)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:213)
... 6 more
walter
The issue here is that you're attempting to parse an array into an object with keys start, file, dummy and link. You need to parse the root array into a JsonArray, then get the individual elements from that.
In its simplest form, something like this will work:
JsonArray root = parser.parse(inputLine).getAsJsonArray();
String searchedTerm = root.get(0).getAsString();
String[] resultTitles = gson.fromJson(root.get(1), String[].class);
String[] dummy = gson.fromJson(root.get(2), String[].class);
String[] links = gson.fromJson(root.get(3), String[].class);
I would suggest creating a custom JsonDeserializer or TypeAdapter to be able to just gson.fromJson() the whole shebang. Since your JSON doesn't have very deep nesting, I think you'll be able to get way with just implementing a JsonDeserializer. Just be aware that if you start running into performance issues, you might want to implement a TypeAdapter. Read more about their differences here.
Try this one out:
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import java.lang.reflect.Type;
public class Main {
public static void main(String[] args) {
String inputLine = "[\"aa\",[\"Aarhus\",\"Aalen\",\"Aalborg\",\"Aargau\",\"Aare\"],[\"\",\"\",\"\",\"\",\"\"],[\"https://wiki.openstreetmap.org/wiki/Aarhus\",\"https://wiki.openstreetmap.org/wiki/Aalen\",\"https://wiki.openstreetmap.org/wiki/Aalborg\",\"https://wiki.openstreetmap.org/wiki/Aargau\",\"https://wiki.openstreetmap.org/wiki/Aare\"]]";
Gson gson = new GsonBuilder()
.registerTypeAdapter(OsmWikiResult.class, new WikiSearchResultDeserializer())
.create();
OsmWikiResult result = gson.fromJson(inputLine, OsmWikiResult.class);
System.out.println("result.getSearchTerm() = " + result.getSearchTerm());
System.out.println("result.getResults() = " + String.join(", ", result.getResults()));
System.out.println("result.getLinks() = " + String.join(", ", result.getLinks()));
}
}
class WikiSearchResultDeserializer implements JsonDeserializer<OsmWikiResult> {
#Override
public OsmWikiResult deserialize(
JsonElement json,
Type typeOfT,
JsonDeserializationContext context
) throws JsonParseException {
JsonArray root = json.getAsJsonArray();
String searchTerm = root.get(0).getAsString();
String[] results = context.deserialize(root.get(1), String[].class);
String[] dummy = context.deserialize(root.get(2), String[].class);
String[] links = context.deserialize(root.get(3), String[].class);
return new OsmWikiResult(searchTerm, results, dummy, links);
}
}
class OsmWikiResult {
private String searchTerm;
private String[] results;
private String[] dummy;
private String[] links;
public OsmWikiResult(String searchTerm, String[] results, String[] dummy, String[] links) {
this.searchTerm = searchTerm;
this.results = results;
this.dummy = dummy;
this.links = links;
}
public String getSearchTerm() { return searchTerm; }
public String[] getResults() { return results; }
public String[] getDummy() { return dummy; }
public String[] getLinks() { return links; }
}
Notice how you need to register the deserializer with Gson so that it knows what to do when parsing an OsmWikiResult. The deserializer just plucks out the array's elements in correct order from the API result's array.
I am trying to read config.yaml file using the snakeYaml library in java.
I am able to get the Module name (i.e [{ABC=true}, {PQR=false}]) in my config file.
Is there a way where I can directly read the value of ABC (ie true) using the code.
I have tried to search online but they are not exactly what I am looking for.
Few links that I went through mentioned below:
Load .yml file into hashmaps using snakeyaml (import junit library)
https://www.java-success.com/yaml-java-using-snakeyaml-library-tutorial/
config.yaml data:
Browser: FIREFOX
Module Name:
- ABC: Yes
- PQR: No
Below is the code that I am using
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.Reader;
import java.util.Map;
import org.yaml.snakeyaml.Yaml;
public class YAMLDemo {
public static void main(String[] args) throws FileNotFoundException {
Yaml yaml = new Yaml();
Reader yamlFile = new FileReader("./config.yaml");
Map<String , Object> yamlMaps = yaml.load(yamlFile);
System.out.println(yamlMaps.get("Browser"));
System.out.println(yamlMaps.get("Module Name"));
}
}
Console Output:
FIREFOX
[{ABC=true}, {PQR=false}]
Any help is really appreciated. Thanks in advance.
If you step through the code with a debugger, you can see that module_name is deserialised as an ArrayList<LinkedHashMap<String, Object>>:
You just need to cast it to the correct type:
public static void main(String[] args) throws FileNotFoundException {
Yaml yaml = new Yaml();
Reader yamlFile = new FileReader("./config.yaml");
Map<String , Object> yamlMaps = (Map<String, Object>) yaml.load(yamlFile);
System.out.println(yamlMaps.get("Browser"));
final List<Map<String, Object>> module_name = (List<Map<String, Object>>) yamlMaps.get("Module Name");
System.out.println(module_name);
System.out.println(module_name.get(0).get("ABC"));
System.out.println(module_name.get(1).get("PQR"));
}
public class YamlParser {
public YamlParser() {
}
public void parse(Map<String, Object> item, String parentKey) {
for (Entry entry : item.entrySet()) {
if (entry.getValue() != null && entry.getValue() instanceof Map) {
parse((Map<String, Object>) entry.getValue(),
(parentKey == null ? "" : parentKey + ".") + entry.getKey().toString());
} else {
System.out.println("map.put(\"" + (parentKey == null ? "" : parentKey + ".") + entry.getKey() + "\",\""
+ entry.getValue() + "\");");
}
}
}
public static void main(String[] args) {
try {
Yaml yaml = new Yaml();
InputStream inputStream = new FileInputStream(
"path-to-application.yml");
Map<String, Object> obj = yaml.load(inputStream);
YamlParser parser = new YamlParser();
parser.parse(obj, null);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
#Devstr has provided you With a good description on how to figure out the data structures.
Here you have an example of how you can read the values into a Properties Object:
final Properties modules = new Properties();
final List<Map<String, Object>> values = (List<Map<String, Object>>) yamlMaps.get("Module Name");
values.stream().filter(Objects::nonNull)
.flatMap(map -> map.entrySet().stream())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))
.forEach((key, value) -> {
modules.put(key, value);
});
System.out.println(modules.get("ABC"));
System.out.println(modules.get("PQR"));
I have a JSON REST endpoint response and I wanted to get the value of hotelNbr from it. How do i do it ?
{
"found": [
{
"hotelNbr": 554050442,
"hotelAddress": "119 Maven Lane, New Jersey",
}
],
"errors": []
}
I am using the below code to get it but it fails in below mentioned line:
public List<Hotel> RDS_POST_HotelDetails(String HotelName, String sUrl) throws Exception, IOException {
Gson gson = new GsonBuilder().setPrettyPrinting().create();
// Create your http client
CloseableHttpClient httpclient = HttpClientBuilder.create().build();
// Create http Put object
HttpPost ohttppost = new HttpPost(sUrl);
// Message Body
StringEntity input = new StringEntity(
"{\"hotelNbr\":[\""+HotelName+"\" ]}"
);
// Set content type for post
input.setContentType("application/json");
// attach message body to request
ohttppost.setEntity(input);
// submit request and save response
HttpResponse response = httpclient.execute(ohttppost);
// Get response body (entity and parse to string
String sEntity = EntityUtils.toString(response.getEntity());
List<Hotel> hotelobject = new ArrayList<Hotel>();
// Create a type token representing the type of objects in your json response
// I had to use the full class path of TYPE because we also have a Type class in our project
java.lang.reflect.Type cType = new TypeToken<List<Hotel>>() {
}.getType();
// Convert to Array object using gson.fromJson(<json string>,
// <type>)
hotelObject = gson.fromJson(sEntity, cType); // I am getting error here
String hotelNumber = hotelObject.get(0).getFound().get(0).getItemNbr().toString();
}
Please find the Hotel.java class below
package com.hotels.company;
import java.util.List;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Hotel {
#SerializedName("found")
#Expose
private List<Found> found = null;
#SerializedName("errors")
#Expose
private List<Object> errors = null;
public List<Found> getFound() {
return found;
}
public void setFound(List<Found> found) {
this.found = found;
}
public List<Object> getErrors() {
return errors;
}
public void setErrors(List<Object> errors) {
this.errors = errors;
}
}
Please find Found.java class below :
package com.hotels.company;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Found {
#SerializedName("hotelNbr")
#Expose
private Integer hotelNbr;
#SerializedName("hotelAddress")
#Expose
private String hotelAddress;
public Integer getHotelNbr() {
return hotelNbr;
}
public void setHotelNbr(Integer hotelNbr) {
this.hotelNbr = hotelNbr;
}
public String getHotelAddress() {
return hotelAddress;
}
public void setHotelAddress(String hotelAddress) {
this.hotelAddress = hotelAddress;
}
}
I tried finding some examples in StackOverflow questions but didn't get solution for mine. Any help will be appreciated.
The JSON you are parsing is not well formatted..
There is a comma after "hotelAddress" remove that
Correct JSON would be:
{
"found":[
{
"hotelNbr":554050442,
"hotelAddress":"119 Maven Lane, New Jersey"
}
],
"errors":[ ]
}
I found a couple of issues:
Json is not valid. Observe there is a comma at the end of "hotelAddress": "119 Maven Lane, New Jersey",. Remove it.
You are trying to deserialize the json into List<Hotel>, but the json mentioned is not a list. Either update the json or deserialise it into Hotel object instead of List.
I am trying to build a JSON string as server response with the aid of the Jackson library. If the route is not 0 I am getting tis response {"status":201,"routes":null} but I have problem to set the status variable to 204 in the SDBean class if the routeD is 0 I am getting in the console this output {"status":204,"routes":[1,9,3]} but in POSTMAN chrome extension the respose takes too long and I am getting this output The response status was 0.
Check out the W3C XMLHttpRequest Level 2 spec for more details about when this happens.
I want to get the following if routeD is not 0 to get {"status":201} else {"routes": {1,3,9}}
How can I manage that with Jakson?
Receiver class:
#Path("/data")
public class Receiver {
#POST
#Consumes(MediaType.APPLICATION_JSON)
public Response storeData(Data data) {
Database db = new Database();
String macD = data.getMac();
int routeD = data.getRoute();
double latD = data.getLatitude();
double longD = data.getLongitude();
double speedD = data.getSpeed();
SDBean bean = new SDBean();
if (routeD != 0) {
bean.status = db.insertData(macD, routeD, latD, longD);
return Response.status(bean.status).entity(bean.toJson()).build();
} else {
bean.routes = db.detectRoute(latD, longD);
return Response.status(bean.status).entity(bean.toJson()).build();
}
}
}
SDBean class:
import java.util.ArrayList;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class SDBean {
public int status;
public ArrayList<Integer> routes;
public String toJson() {
ObjectMapper mapper = new ObjectMapper();
String json = null;
if(status == 0){
this.status = 204;
}
try {
json = mapper.writeValueAsString(this);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return json;
}
}
Your problem with 0 response due to you don't initialize your int value inside bean. When you try to analize your code :
//Inside Receiver
return Response.status(bean.status).entity(bean.toJson()).build();
In this line you first get value from status field from bean. It's initialize with default value of 0 (Oracle documentation about primitive data types and default values) and next you map it toJson() where you set it's value to status response 204 in this line :
//Inside SDBean
if(status == 0){
this.status = 204;
}
I suggest one of this resulutions:
Initialize variable inline:
public int status = 204;
If you need some additional logic you could use static initialization block
static {
//additional logic here
status = 204;
}
Or simply use constructor in your case:
public SDBean(){
//additional logic here
status = 204;
}
For more info here you have documentation: Initializing fields.
Also you don't add anything to your ArrayList. Try to initialize it inside your bean inline:
public ArrayList<Integer> routes = new ArrayList<Integer>();
or if you use jdk 1.7+ use diamond interfece instead
public ArrayList<Integer> routes = new ArrayList<>();
And now you can use it to add your data inside storeData class:
bean.routes.add(yourIntValue);
// EDIT:
package com.gmail.at.mironiuk.kacper.stack.overflow.wtf;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
#Path("/data")
public class Receiver {
#POST
#Consumes(MediaType.APPLICATION_JSON)
public Response storeData(Data data) {
Database db = new Database();
SDBean bean = new SDBean();
String macD = data.getMac();
int routeD = data.getRoute();
double latD = data.getLatitude();
double longD = data.getLongitude();
double speedD = data.getSpeed();
if (routeD != 0) { // here you always will have null or empty case you only set your status here
bean.status = db.insertData(macD, routeD, latD, longD); // In this if try to add sth to your list
bean.status = 204;
return Response.status(bean.status).entity(bean.toJson()).build(); //Expected result {"status":"204", "routes": []}
} else { // here your List will be this whats you returns from
bean.routes = db.detectRoute(latD, longD); // <- this function and i don't know what function returns
return Response.status(bean.status).entity(bean.toJson()).build(); //Expected result {"status":"204", "routes": [?,?,?]}
}
}
}
I hope that I help you
I have a web service that returns JSON strings one by one based on query inputs, a GET request to the service returns this (there's only one entry in the database)
[{"checked":false,"dateposted":"2014-10-23T00:00:00","itemnumber":1,"quantity":5,"stockcheckid":1}]
at the moment I just have this System.out.println in a while loop.
what I want to do is be able to access these results in a way that I can input them into a jtable to display on a client application. I've read some guides about reading from JSON files etc but I cant find anything specific to REST web services. I hear GSON mentioned a lot, i tried that but i cant quite work out how to make it work in this context
I should also mention that the service can also send this data in XML format.
Do I somehow create a JSON file appending each new entry to it? and then populate the table from that file?
anyway here's the code that initiates the GET request.
public static void getRequest(String dataGet) {
try {
URL url = new URL("http://localhost:8080/nXXXXXXXXc/webresources/entities.stockchecks/" + dataGet);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty("Accept", "application/json");
if (conn.getResponseCode() != 200) {
throw new RuntimeException("Failed : HTTP error code : "
+ conn.getResponseCode());
}
BufferedReader br = new BufferedReader(new InputStreamReader(
(conn.getInputStream())));
String output;
while ((output = br.readLine()) != null) {
System.out.println(output);
}
conn.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}`
The response is a map. You can serialise a JSON map to a Java map with Jackson like this:
import static org.junit.Assert.assertEquals;
import java.io.IOException;
import java.util.Map;
import java.util.TreeMap;
import org.junit.Test;
import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class JSONtoMap {
public static final String json = "{\"B\":\"b\",\"C\":\"c\"}";
public static class POJO{
private Map<String,String> map = new TreeMap<String,String>();
#JsonAnyGetter
public Map<String, String> get() {
return map;
}
#JsonAnySetter
public void set(String name, String value) {
map.put(name, value);
}
}
#Test
public final void test() throws JsonProcessingException, IOException {
ObjectMapper jsonmapper = new ObjectMapper();
POJO p = jsonmapper.readValue(json, POJO.class);
assertEquals(jsonmapper.writeValueAsString(p),json);
}
}
I imagine you could do something similar with GSON. Another option is if you know the structure of the JSON object - in that case you make a simple POJO version and de-serialise into that instead of something like the POJO class I've defined above.
More detail and a similar version that supports XML as well as JSON mapping
Irrespective of how you obtain the data, use it to construct a suitable TableModel and use that model to construct the JTable. In this example, the model accesses a Map<String, String> to fulfill the TableModel contract; you can substitute the Map obtained using the approach shown here. Because loading the data may take an indeterminate amount of time, use a SwingWorker, as shown here.
This is simply a combination of trashgod's and tom's answer, with an example, using Jackson and a TableModel. I really just want to give camickr's BeanTableModel/RowTableModel (which is a generic class to help us easily create table models to from pojos) a try (seems to work great).
For more information/details please see this post
Entity class (properties mapped to the keys in your json)
public class Entity {
// field/property names must match to your json keys (with some exceptions)
// other wise we are required to use further annotations
private boolean checked;
private Date dateposted;
private int itemnumber;
private int quantity;
private int stockcheckid;
/*** ----- DO NOT FORGET GETTERS AND SETTERS ---- ***/
}
Main class. Note the use BeanTableModel. You will need to download this class along with RowTableModel from the link above.
public class JsonTableDemo {
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
String json = "[{\"checked\":false,\"dateposted\":\"2014-10-23T00:00:00\",\"itemnumber\":1,\"quantity\":5,\"stockcheckid\":1}]";
List<Entity> response = mapper.readValue(json,
TypeFactory.defaultInstance().constructCollectionType(
List.class, Entity.class));
RowTableModel model = new BeanTableModel<>(Entity.class, response);
JTable table = new JTable(model) {
#Override
public Dimension getPreferredScrollableViewportSize() {
return getPreferredSize();
}
};
JOptionPane.showMessageDialog(null, new JScrollPane(table));
}
}
Result
Note, for long running task (many io task included), such as requesting a rest resource, you should use a SwingWorker as explained by trashgod. When the repsonse comes in, you can basically addRow to the RowTableModel instance. For instance if we use the same json response and model as above, we could simply do something like
response = mapper.readValue(json,
TypeFactory.defaultInstance().constructCollectionType(
List.class, Entity.class));
for (Entity entity : response) {
model.addRow(entity);
}
UPDATE
I should also mention that the service can also send this data in XML format.
Looking at your json, it is an array of objects. With XML, the format is a little different, as you must have a root document element. So you can't just have say
<entity>
<prop></prop>
</entity>
<entity>
<prop></prop>
</entity>
It would need to be something like
<entities>
<entity>
<prop></prop>
</entity>
<entity>
<prop></prop>
</entity>
</entities>
That being said, using data binding, the easiest way would be to create another class to wrap a List<Entity>. Now I'm not too familiar with Jackson's XML capabilities/features, but using JAXB, you can have a class like:
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class Entities {
#XmlElement(name = "entity")
protected List<Entity> entities;
public List<Entity> getEntities() {
if (entities == null) {
entities = new ArrayList<>();
}
return entities;
}
public void setEntities(List<Entity> entities) {
this.entities = entities;
}
}
Then you can unmarshal the below XMl into the Entities class. Here's an update demo to show both json and xml
public class JsonTableDemo {
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
String json = "[{\"checked\":false,\"dateposted\":\"2014-10-23T00:00:00\",\"itemnumber\":1,\"quantity\":5,\"stockcheckid\":1}]";
List<Entity> response = mapper.readValue(json,
TypeFactory.defaultInstance().constructCollectionType(
List.class, Entity.class));
RowTableModel jsonModel = new BeanTableModel<>(Entity.class, response);
JTable jsonTable = new JTable(jsonModel) {
#Override
public Dimension getPreferredScrollableViewportSize() {
return getPreferredSize();
}
};
String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n"
+ "<entities>\n"
+ " <entity>\n"
+ " <checked>false</checked>\n"
+ " <dateposted>2014-10-22T17:00:00-07:00</dateposted>\n"
+ " <itemnumber>1</itemnumber>\n"
+ " <quantity>5</quantity>\n"
+ " <stockcheckid>1</stockcheckid>\n"
+ " </entity>\n"
+ "</entities>";
JAXBContext context = JAXBContext.newInstance(Entities.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
Entities entities = (Entities)unmarshaller.unmarshal(new StringReader(xml));
RowTableModel<Entity> xmlModel = new BeanTableModel<>(
Entity.class, entities.getEntities());
JTable xmlTable = new JTable(xmlModel){
#Override
public Dimension getPreferredScrollableViewportSize() {
return getPreferredSize();
}
};
JPanel panel = new JPanel(new GridLayout(0, 1));
JPanel jsonPanel = new JPanel(new BorderLayout());
jsonPanel.add(new JLabel("JSON Table", SwingConstants.CENTER), BorderLayout.PAGE_START);
jsonPanel.add(new JScrollPane(jsonTable));
panel.add(jsonPanel);
JPanel xmlPanel = new JPanel(new BorderLayout());
xmlPanel.add(new JLabel("XML Table", SwingConstants.CENTER), BorderLayout.PAGE_START);
xmlPanel.add(new JScrollPane(xmlTable));
panel.add(xmlPanel);
JOptionPane.showMessageDialog(null, new JScrollPane(panel));
}
}
See more about using JAXB