2

I have created the REST service successfully with accessing to the MS SQL database, and I am getting the JSON object as well, and also I have created the GUI for REST client in NetBeans normal java Application. Rather than client accessing to database and fetching data directly, what I want is to fill the JTable from the received JSON object. Your help really appreciate.

client code is this. this is just to print it in console.

public void getJSONEmployees() {
    try {
        Client cl = Client.create();
        WebResource webResource = cl
                .resource("http://localhost:8080/rest_server/rest/jersey/dbAccess/getDBVal");
        ClientResponse response = webResource.accept("application/json")
                .get(ClientResponse.class);

        if (response.getStatus() != 200) {
            System.out.println("no out put");
            throw new RuntimeException("Failed : HTTP error code : "
                    + response.getStatus());
        }

        String output = response.getEntity(String.class);
        // String[] output = response.getEntity(String.);
        System.out.println("\n -------");
        System.out.println(output);

    } catch (Exception e) {
        e.printStackTrace();
    }
}

I want to load data in to that jTable after the button click event. From JSON key value pair, values i need to display in row wise.

Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
  • Can you please post your code here, so that anybody can give you answer correctly. – MrYo Aug 21 '14 at 04:41
  • It is for desktop App. I need it for swing jTable. I want to extract that object to put in to that jtabel, I tried that JSON object to getting it to an String array, but Splitting is difficult there, since it has curly brackets, square brackets, colon, comma. – Cristine Angelena Aug 21 '14 at 07:53
  • OK see my answer. That will help you out. – Paul Samsotha Aug 21 '14 at 07:55
  • Is the structure of the JSON always the same? Could the ReST service sometimes return, say, a Car object and sometimes a Truck with different fields? – Thorn Aug 21 '14 at 11:46

2 Answers2

8

IMO, the best way to handle this is to use a library like Jackson for json-to-object-mapping (or data binding) and just map your json objects to a regular java object. Then just use a custom AbstractTableModel to hold a list of the those object. You can easily map the object attributes to table column values in the getValueAt() method of your table model..

For example

User class

public class User {

    private String firstName;
    private String lastName;

    public String getFirstName() { return firstName; }
    public String getLastName() { return lastName; }
    public void setFirstName(String firstName) { this.firstName = firstName; }
    public void setLastName(String lastName) { this.lastName = lastName; }
}

UserTableModel class - (Note, this is the simplest of cases. You may want to add some methods to add rows and remove rows and such. You will need to add that functionality your self. There are many good posts here on SO. You may want to go through @MadProgrammer's profile and check out his abstracttablemodel tagged answers or just check out the tag in general).

import java.util.ArrayList;
import java.util.List;

import javax.swing.table.AbstractTableModel;

public class UserTableModel extends AbstractTableModel {

    private List<User> userData = new ArrayList<User>();
    private String[] columnNames =  {"First Name", "Last Name"};

    public UserTableModel() {}

    public UserTableModel(List<User> userData) {
        this.userData = userData;
    }

    @Override
    public String getColumnName(int column) {
        return columnNames[column];
    }

    @Override
    public int getColumnCount() {
        return columnNames.length;
    }

    @Override
    public int getRowCount() {
        return userData.size();
    }

    @Override
    public Object getValueAt(int row, int column) {
        Object userAttribute = null;
        User userObject = userData.get(row);
        switch(column) {
            case 0: userAttribute = userObject.getFirstName(); break;
            case 1: userAttribute = userObject.getLastName(); break;
            default: break;
        }
        return userAttribute;
    }

    public void addUser(User user) {
        userData.add(user);
        fireTableDataChanged();
    }
}

Main class - which uses the ObjectMapper class from Jackson.

import java.awt.Dimension;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;

import com.fasterxml.jackson.databind.ObjectMapper;

public class MainJsonToObjectDemo {

    public static void main(String[] args) throws Exception {
        SwingUtilities.invokeLater(new Runnable(){
            public void run() {
                String jsonUser1 = "{ \"firstName\": \"Stack\", \"lastName\": \"Overflow\"}";
                String jsonUser2 = "{ \"firstName\": \"Pee\", \"lastName\": \"Skillet\"}";
                ObjectMapper mapper = new ObjectMapper();
                User user1 = null;
                User user2 = null;
                try {
                    user1 = mapper.readValue(jsonUser1, User.class);
                    user2 = mapper.readValue(jsonUser2, User.class);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                List<User> users = new ArrayList<User>();
                users.add(user1);
                users.add(user2);
                UserTableModel model = new UserTableModel(users);
                JTable table = new JTable(model) {
                    @Override
                    public Dimension getPreferredScrollableViewportSize() {
                        return new Dimension(300, 100);
                    }
                };
                JOptionPane.showMessageDialog(null, new JScrollPane(table));
            }
        });
    }
}

enter image description here

Here are some references you can go to for more information:

  • How to use Tables: Creating a Table Model
  • Jackson Homepage
  • Jackson wiki with links to tutorials
  • See the GitHub for the jackson-databind dependency. If you're using maven, add this as a dependency, will grab the necessary jackson-core and jackson-annotation dependencies also.

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.3.3</version>
    </dependency>
    

    If you aren't using maven, make sure you download the jackson-core and jackson-annotation also. They each have their own GitHub page that has to link to the download in the Maven Central Repo.

  • Have a look at Rob Camick's BeanTableModel. It's generic TableModel that will allow you to create a table model from many of your business objects, so you don't have to go through the hassle of creating your own.


UPDATE

Here is an example that adds user dynamically at run time, making use of the addUser method of the UserTableModel. Type in a "User json object" and hit Add User

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;

import com.fasterxml.jackson.databind.ObjectMapper;

public class MainJsonToObjectDemo {

    private JTextArea areaToWriteJson = new JTextArea(6, 30);
    private ObjectMapper objectMapper = new ObjectMapper();
    private JButton addUserButton = getAddUserButton();
    private JTable userTable = getUserTable(300, 150);
    private JFrame frame = new JFrame("Json Objects JTable Demo");

    public MainJsonToObjectDemo() {
        initTableData();
        frame.add(new JScrollPane(areaToWriteJson), BorderLayout.PAGE_START);
        frame.add(addUserButton, BorderLayout.CENTER);
        frame.add(new JScrollPane(userTable), BorderLayout.PAGE_END);
        frame.pack();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    private JTable getUserTable(final int width, final int height) {
        UserTableModel model = new UserTableModel();
        JTable table = new JTable(model) {
            @Override
            public Dimension getPreferredScrollableViewportSize() {
                return new Dimension(width, height);
            }
        };
        return table;
    }

    private JButton getAddUserButton() {
        JButton button = new JButton("Add User");
        button.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                String json = areaToWriteJson.getText();
                if (!json.isEmpty()) {
                    addUser(json);
                }
            }
        });
        return button;
    }

    private void addUser(String jsonString) {
        User user = null;
        try {
            user = objectMapper.readValue(jsonString, User.class);
            ((UserTableModel) userTable.getModel()).addUser(user);
            areaToWriteJson.setText("");
        } catch (Exception e) {
            JOptionPane.showMessageDialog(frame,
                    "Could not map text to User object. Check your formatting: \n"
                    + "{\n"
                    + "    \"firstName\": \"<First>\",\n"
                    + "    \"lastName\": \"<Last>\"\n"
                    + "}", "Error Mapping",
                    JOptionPane.ERROR_MESSAGE);
        }   
    }

    private void initTableData() {
        String jsonUser1 = "{ \"firstName\": \"Stack\", \"lastName\": \"Overflow\"}";
        String jsonUser2 = "{ \"firstName\": \"Pee\", \"lastName\": \"Skillet\"}";
        addUser(jsonUser1);
        addUser(jsonUser2);
    }

    public static void main(String[] args) throws Exception {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new MainJsonToObjectDemo();
            }
        });
    }
}

UPDATE

"there it will return Employee List as a JSON Array"

If you have a json array, you can easily convert that to a Java List with the ObjectMapper. You can pass a CollectionType as the second argument to the readValue, by using TypeFactory#constructCollectionType. Something like

import java.util.List;
import javax.swing.*;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.TypeFactory;

public class UserListDemo {

    public static void main(String[] args) throws Exception {
        String jsonUsers = 
                 "["
                +  "{ \"firstName\": \"Stack\", \"lastName\": \"Overflow\" },"
                +  "{ \"firstName\": \"Pee\", \"lastName\": \"Skillet\" }" 
                +"]";
        ObjectMapper mapper = new ObjectMapper();
        List<User> users = mapper.readValue(
                jsonUsers,
                TypeFactory.defaultInstance().constructCollectionType(
                        List.class, User.class));
        UserTableModel model = new UserTableModel(users);
        JTable table = new JTable(model);
        table.setPreferredScrollableViewportSize(table.getPreferredSize());
        JOptionPane.showMessageDialog(null, new JScrollPane(table));
    }
}

enter image description here

Community
  • 1
  • 1
Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
  • It is somewhat confusing to me, But my REST service is running on Eclipe, there it will return Employee List as a JSON Array. I want to Consume that object using an URL in netBeans desktop client app to fill the data to table. actually is it possible ? I was able to get data to client app as I mentioned in the question.but the thing is how to extract that object to fill the table. – Cristine Angelena Aug 21 '14 at 12:59
  • I'm not sure how much better I can explain this. My answer use Jackson (I have the links to the jars you need). I use the `ObjectMapper` (from Jackson) to map the json String to a `User` class. You can do the same with an `Employee` class. Then create a table model based on that `Employee` class. I also provided a link to `BeanTableModel` which is a generic table model you can use for your `Employee` objects. – Paul Samsotha Aug 21 '14 at 13:03
  • See my Update for converting the json array to a `List` – Paul Samsotha Aug 23 '14 at 03:24
0

Java8 will add JSON support to the J2SE, rendering Jackson, GSON, et al, extraneous. This isn't to say that they won't be used (inertia is difficult to get rid of after all). For those who don't have old, bad habits or are trying to get rid of them (I fall in the latter camp), the code looks something like:

private SomeCollectionProvider collections;

private JsonBuilderFactory builderFactory;

public JsonArray collectionToJsonArray() {
    return collections.createACollection()
            .stream()
            .map(myObject -> myObject.id) // field is public
            .collect(
                    builderFactory::createArrayBuilder,
                    (a, s) -> a.add(s),
                    (b1, b2) -> b1.add(b2))
            .build();
}
hd1
  • 33,938
  • 5
  • 80
  • 91