populate a jtable with json string results from a

2019-08-08 05:58发布

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();

  }

}`

3条回答
女痞
2楼-- · 2019-08-08 06:24

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.

查看更多
神经病院院长
3楼-- · 2019-08-08 06:29

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

enter image description here


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));
    }
}

enter image description here

查看更多
\"骚年 ilove
4楼-- · 2019-08-08 06:36

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

查看更多
登录 后发表回答