That's fine :-), I'll set up the enviroment. I'll have a server package with a Client class and a server package with the Server class, then a resource package with the Customer and the Product. Once question, what do you mean when you say

(you'll need those in both the client and the server.)
Do you mean that both CLient and Server classes will have to hold an object of type Product and Customer?

Do you mean that both CLient and Server classes will have to hold an object of type Product and Customer?

They both need access to the class definitions. We assume the Server has access to many instances of Customer and Product. On request it serialises one (or more) instances in JSON format and sends it to the Client, that uses the JSON data to create an Instance that should be a copy of the instance on the server.

Hi sorry, still setting things up as I wasn't around that much yesterday and today
I set up the Customer and Product as you said.
Here are the CLient, Server and testClass so far
Client

package Client;

import Server.Server;
import resources.Customer;
import resources.Product;

public class Client {
    private Server server;
    private Customer customer;
    private Product product;

    public Server getServer() {
        return server;
    }

    public void setServer(Server server) {
        this.server = server;
    }

    public Client(Server server) {
        this.server = server;
    }
}

Server

package Server;

import resources.Customer;
import resources.Product;

public class Server {
    private Customer customer;
    private Product product;

   public Object getResource(String type, int id) {
        switch (type) {
            case "Customer":
                return new Customer(id, "Customer_" + id);
            case "Product":
                return new Product(id, "Product_" + id);
        }
        return null;
    }

}

TestClass

package testClass;

import Client.Client;
import Server.Server;
import resources.Customer;
import resources.Product;

public class TestClass {

    private static Client client;
    private static Server server;
    private static Customer customer;
    private static Product product;

    public static void main(String[] args) {
        server = new Server();
        client = new Client(server);

        customer = (Customer) server.getResource("Customer", 4);
        product = (Product) server.getResource("Product", 24);
        //test();
    }
    public static void test() {
//    System.out.println(client.get(Customer.class, 1));
//    System.out.println(client.get(Product.class, 2));        
   // should print the toString for Customer and Product
        System.out.println(customer);
        System.out.println(product);
    }

}

A couple of quick comments:
no need for get/set server in client!

Test:
Soon after posting I edited the post to improve the test code to pass the resource class rather than a name to the client method that performs the request. Apart from being more logical, it also removes the need for the horrible unsafe casts - I see you have it commented out, but that is the version you should use. The test code calls a Client method, that you need to write, to construct the REST request and pass that to the server. I should have a signature something like
public <T> T get(Class<T> t, int id)
ie tell me what class of object, and what it's ID (primary key) is, and I'll return you the instance of that class

Server getRsource should be private. That's it's back-end database and there's no way the client can eccess that directly. Server needs a public method like
String request(String request) // returns requested resource as JSON

that accepts the REST request and returns the resource in the format specified in the accept. That's the method the client will call.

I see you have it commented out, but that is the version you should use.

I did yes, but I've uncommented that after and used it

public <T> T get(Class<T> t, int id)
Yep, I figured that out after my post, :-)

e tell me what class of object, and what it's ID (primary key) is, and I'll return you the instance of that class

Presumably that method, once we know what class has been passed to it, will have to create an instance of that class based so that I can get the class name and id and construct the REST request to pass to the server. If that method returns the instance of the class that makes me think that it will be the responsibility of the TestMethod to create the request.
What I'm saying I suppose is the get(Class<T> t, int id) will do this in its body

find out which class has been passed to it
create a class of that type and populate its fields
use its fields to construct the request
pass the request to the server

It's a lot lot simpler than that!
Remember what's in the request? A string that identifies the kind of resource (ie its class) and the id. That's all.
(The string can be just the class's name - as in t.getName() )

Right, so here is what I came up with, following your suggestions
The test class

package testClass;

import Client.Client;
import Server.Server;
import resources.Customer;
import resources.Product;

public class TestClass {

    private static Client client;
    private static Server server;
    private static Customer customer;
    private static Product product;

    public static void main(String[] args) {
        server = new Server();
        client = new Client(server);
        test();
    }
    public static void test() {
        client.get(Customer.class, 1);
        client.get(Product.class, 2);
    }

}

has the test method calling the client's get.
Client

package Client;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

import Server.Server;
import resources.Customer;
import resources.Product;

public class Client {
    private Server server;
    private Customer customer;
    private Product product;

    public Client(Server server) {
        this.server = server;
    }

    public <T> T get(Class<T> class1, int ID) {
        String restRequest = class1.getSimpleName() + " " + ID; 
        String encodedRequest = "";
        try {
            encodedRequest = URLEncoder.encode(restRequest, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        String requestType = "GET";
        String typeAccepted = "Accept:application/json";
        String fullRequest = requestType + " " + encodedRequest + " " + typeAccepted;       
        server.generateJsonResponse(fullRequest);

        return (T) class1;
    }
}

The client also encodes the request and sends it to the server, well, calls a method in the Server class I should say
Server

package Server;

import java.net.URLEncoder;

import resources.Customer;
import resources.Product;

public class Server {
    private Customer customer;
    private Product product;

    private Object getResource(String type, int id) {
        switch (type) {
            case "Customer":
                return new Customer(id, "Customer_" + id);
            case "Product":
                return new Product(id, "Product_" + id);
        }
        return null;
    }
    public String generateJsonResponse(String request) {        
        int beginIndex = 0;
        int endIndex = 0;
        for(int i = 0; i < request.length(); i++) {
            if(request.charAt(i) == ' ' && beginIndex == 0) {
                beginIndex = i; 
            }
            else if(request.charAt(i) == ' ' && beginIndex != 0) {
                endIndex = i; 
            }
        }

        String restUrl = request.substring(beginIndex, endIndex).trim();
        String[] splitStringReq = splitString(restUrl, "\\+");
        String resourceType = splitStringReq[0];
        int ID = Integer.parseInt(splitStringReq[1]);
        Object resourceGenerated = getResource(resourceType, ID);
        String formattedResponse = formatResponse(resourceGenerated);
        System.out.println(formattedResponse);      
        return formattedResponse;
    }

    private String[] splitString(String stringToSplit, String charToSplitAt) {
        String[] splitStrings = stringToSplit.split(charToSplitAt);
        for(int i = 0; i < splitStrings.length; i++) {
            System.out.println(splitStrings[i]);
        }
        return splitStrings;
    }

    private String formatResponse(Object resourceGenerated) {

        //String response = "{\"" + getResourceName() + "\":{\"id\":" + getID() + ",\"" + "price\":" + getPrice() + "}}"
        String response = "{\"";
        if(resourceGenerated instanceof Customer) {
            customer = (Customer)resourceGenerated;
            int id = customer.getId();
            String name = customer.getName();
            response += "Customer\":{\"id\":" + id + ",\"" + "name\":" + name;
        }
        else if(resourceGenerated instanceof Product) {
            product = (Product)resourceGenerated;
            int id = product.getId();
            String name = product.getName();
            response += "Product\":{\"id\":" + id + ",\"" + "name\":" + name;

        }

        response += "}}";

        return response;
    }

}

The server takes the request, creates a substring so to keep just the URL, splits it at the + sign (which is what the encode generates) then formats the response and returns it to the client.

The Customer and Product are the same as the ones you posted.
The output generated is

{"Customer":{"id":1,"name":Customer_1}}
{"Product":{"id":2,"name":Product_2}}

Great progress!
The returned string should start with an HTTP return code, and the JSON needs to be passed as a mime type file - but these are HTTP details that are not specially relevant to learning about REST, so you could just chose to skip them.
The client now needs to parse the returned JSON string and create the corresponding Customer or Product.

You can probably simplify the server's parsing by first splitting the whole request on white space so you get {request type, url, accept clause}. Don't forget to reverse the URL encoding.

In the event that you are finding out about REST messages, at that point it doesn't make a difference how the messages are sent and got, so passing them in normal strategy calls is the least difficult approach to do it.

The client now needs to parse the returned JSON string and create the corresponding Customer or Product.

OK, but just to clarify, when the client parses the response - let's say that I leave the returned json as it is without getting the server to split the request because the client now has the json string as I needed it to be I think - to create the Customer and Product object do you mean using JSONParser and JSONObject (or any other library for that matter) because I remember that in a previous thread you said that it might have been better not to use those in this example?

In the event that you are finding out about REST messages

I guess not yet :-)

well, yes. In my opinion you will learn a lot by going through the process of parsing the JSON and creating the objects.
When you've done that try adding something like this to the Customer class
List<Product> purchasedProducts ...// getter and setter as needed for JavaBean compliance
and find out how to handle that in JSON.

Having done that you will understand how to compare JASON with JSONParser etc, and maybe others.

Right, so now the client has some extra methods:
parseJsonResponse which parses the json and createObjFromJson which creates either a Product object or a Customer one.
The output is

Customer{id=1, name=Customer_1}
Product{id=2, name=Product_2}

        ...
        String requestType = "GET";
        String typeAccepted = "Accept:application/json";
        String fullRequest = requestType + " " + encodedRequest + " " + typeAccepted;       
        String generateJsonResponse = server.generateJsonResponse(fullRequest);
        parseJsonResponse(generateJsonResponse);
        return (T) class1;
    }
    private void parseJsonResponse(String generateJsonResponse) {
    String json = "";
    try {
        JSONObject obj = new JSONObject(generateJsonResponse);  
        createObjFromJson(obj);         
    } catch (Exception e) {
        e.printStackTrace();
    }

}

private void createObjFromJson(JSONObject obj) throws JSONException {
    Integer id = null;
    String name = null;
    if(obj.has("Customer")) {
        id = (Integer)obj.getJSONObject("Customer").get("id");
        name = (String)obj.getJSONObject("Customer").get("name");
        customer = new Customer(id, name);
        System.out.println(customer);           
    }
    else if(obj.has("Product")) {
        id = (Integer)obj.getJSONObject("Product").get("id");
        name = (String)obj.getJSONObject("Product").get("name");
        product = new Product(id, name);
        System.out.println(product);
    }

}

Next I will see if I can have the Customer to have a list of products as you've suggested.

I see you are using JSONObject with it's horrible unchecked casts etc. Have fun with that!

While you are coding this, keep in mind what you would have to do for any new classes that need to be added... you have a lot of code that assumes a detailed knowledge of the classes. Is that desrable?
You assume that the classes involved have a constructor that takes all the values you need, but the best you can rely on is that they are javabeans with a no-args constructor and set methods for everything.

I see you are using JSONObject with it's horrible unchecked casts etc. Have fun with that!

Sorry I wasn't sure what else to use to create the json object and then create the objects from there.

You assume that the classes involved have a constructor that takes all the values you need, but the best you can rely on is that they are javabeans with a no-args constructor and set methods for everything.

So you're saying I shouldn't be creating objects like for the Produc and the Customer at all instead? But to set its value I need an object first anyway, so if I don't create it how would i set its value?

The basic process used by JSONObject, JASON, XMLDecoder etc is to create an empty instance of the target class using its no-args constructor, then use its set methods to inject all the data values (including other classes, recursively) from the source file.
You can do that in ordinary Java code, assuming the target class is javabean compliant. I think that's a worthwhile exercise to do once for the deep understanding it will give you. But if you really want to skip straight to the answer i would recommend JASON rather than JSONObject etc. because it's a more complete solution to many of the problems (that you will learn about by doing it yourself).

Hi sorry for the long delay, but sadly it might be like that for a little while.
So, I have a couple of questions following your last post.
OK about what you said, will try to do it just with plain java and no json object, that's fine and I will create the objects using the empty constructors and use the set methods, that's fine
However, in the client I have either the encoded request (restRequest) which looks like this:

Customer+1
Product+2

As they are a combination of the class name and the ID or the fully generated response (generateJsonResponse) which looks like this

{"Customer":{"id":1,"name":Customer_1}}
{"Product":{"id":2,"name":Product_2}}

The server is doing all the substringing, string splitting but it returns the fully generated response already.
Now, for me to create the Customer and Product object in the client I will need to know what type of object I need to create, the name and the id which I need to extract from either the encoded request or from the fully generated response, so does it mean that I will have to "parse" the server response string again and extract all the relevant info? The thing is, how do I split a resonse string like {"Product":{"id":2,"name":Product_2}} to get the bits I need?

Yes, your client has to parse the server's JSON to extract the relevant info (name of class to instantiate, values for its members)
The idea behind the JSON format is that it should be easy to parse (especially in JavaScript, for what that's worth). If you look closely you'll see that curly brackets indicate depth of nesting, and the contents are name and value with a colon between. You might want to see how Customer with list of Products is encoded to see fully how it works. Parsing is just a load of split and substring calls, with recursion for objects inside objects.
Once you have those values there's an interesting question: do you hard code the pasing and creating each class of object (easy but a lot of work with many large classes, and a maintenance nightmare) or do you use a generalised parser and reflection to build a generalised method to create any JavaBean from name:value pairs (not so easy, but you just do it once).

Yes, there's a lot of boring bits involved in the client encoding a request that server then has to decode, then the server converting a nice object structure into a text file, only for the client to have to do a lot of boring stuff to re-build the objects from the text. That's the downside of having a lowest-common-denominator data request/transfer format for general client/server apps that may be in any mixture of languages, maybe not even object oriented.

Hi, sorry been caught into other things on the way.
I've tried to get my head around this again, I'm still in the splitting string phase and I can get this {"Product":{"id":2,"name":Product_2}} to be split into this array of strings

{"Customer":{"id":1
"name":Customer_1}}

But I don't seem to be able to split it any further without getting into issues, ideally I'd like to get to this array of strings instead:

  {"Customer":
  {"id":1
  "name":Customer_1}}

So the methods doing the splits are these

private void parseResponse(String generateJsonResponse) {
        //System.out.println(generateJsonResponse);
        String[] splitObjects = splitObject(generateJsonResponse, ",", 0);

        for(int i = 0; i < splitObjects.length; i++) {          
            System.out.println(splitObjects[i]);
        }           
    }

    private String[] splitObject(String generateJsonResponse, String delimiter, int limit) {        
        String[] split = generateJsonResponse.split(delimiter, limit);

        for(int i = 0; i < split.length; i++) {
            //System.out.println(split[i]);
//          if(split[i].indexOf(':') != -1) {
//              split = splitObject(split[i], ":" , 0);             
//          }       

            //TODO turn into a collection and back into array

            //System.out.println(split[i]);
        }
        TreeSet<String> splitString = new TreeSet<String>(Arrays.asList(split));
        //HashSet<String> splitString = new HashSet<String>(Arrays.asList(split));
        for(String currentString : splitString) {
            //System.out.println(currentString);
        }
        return split;       
    }   

(everything gets copied into TreeSet to avoid duplicates) but the moment is try to split the string even further using the ":" as delimiter and uncommenting this code in splitObject method

if(split[i].indexOf(':') != -1) {
    split = splitObject(split[i], ":" , 0);             
}

then I get only a partial string

{"Customer"
{"id"
1

SO essentially what I'm trying to do there is to split the string first at the "," delimiter, which works, but then I need to split it at the ":" delimiter but only to a certain point, so maybe recursion here isn't the right way because otherwise it keeps splitting the string at any ":" which isn't what I want, does it make sense?

Hi, welcome back.

I haven't done this myself, but my gut tells me that a recursive solution is the way to go. I probably woudn't try to do too much with split because that doesn't have enough context. I'm thinking maybe build the object graph directly from the json, eg more like:

take everything between the opening bracket and the first matching close bracket: this will be an object. (loop this for any remaining brackets)
split at the first colon - that gives name and a list of member values (discard the enclosing brackets)
take up to the first comma ( loop doing this until there are no more commas)
if the value starts with an open bracket this is a new object: use the name to create a new instance of that class and recurse to get a whole object
otherwize its a primitive value and the name is the variable name: set the instance variable to the value

(don't take that too literally, it's straight off the top of my head. Just a way of thinking about it, thats all)

Why go to all this trouble writing everything from scratch?
Far more practical to take an existing framework and write your entire REST call in a few lines of code :)

Building a REST service
https://spring.io/guides/gs/rest-service/

Consuming a REST service
https://spring.io/guides/gs/consuming-rest/

Doing it all yourself is a good learning exercise, and can be fun, but it's far from the most efficient way and extremely error prone.

That's not to say things can't get complicated using things like Spring, but the complexity is at an entirely different level and not something you're going to encounter for basic things like this.

Why go to all this trouble writing everything from scratch?

Blame me; I'm the one who ws pushing this approach. This topic is all about learning about REST and JSON. In my opinion it's near impossible to understand (eg) Spring vs Jackson unless you first understand what JSON is and why it's so totally bloody useless for serving Java objects. Trying to implement a tiny example by hand will make that clear. For a learner it's also a great exercise to write a JSON parser.
But obviously for a real-life application you'ld be mad to do it all yourself from scratch.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.