Results 1 to 10 of 10
  1. #1
    Digital Larry is offline Member
    Join Date
    Mar 2013
    Posts
    57
    Rep Power
    0

    Default Stumped by Json, file I/O, extended class

    I'm making a little CAD system. The fundamental object class is the "SpinBlock":

    Java Code:
    
    import java.util.HashMap;
    import java.util.Map;
    
    public class SpinBlock {
    	
    	// position and name of the block
    	String name = "Default";
    	int x_pos = 0;
    	int y_pos = 0;
    
    	protected Map<String, Double> params = new HashMap<String, Double>();
    
    	public SpinBlock(int x, int y) {
    		// TODO Auto-generated constructor stub
    		x_pos = x;
    		y_pos = y;
    	}
    
    	public Map<String, Double> getParams() {
    		return params;
    	}
    
    	public String getName() {
    		// TODO Auto-generated method stub
    		return name;
    	}
    
    	public int getX() {
    		// TODO Auto-generated method stub
    		return x_pos;
    	}
    
    	public int getY() {
    		// TODO Auto-generated method stub
    		return y_pos;
    	}
    	
    	public void addParam(String s, double d) {
    		params.put(s,d);
    	}
    
    }
    This is never used directly, but here are a couple example specific blocks which are extended from SpinBlock:

    Java Code:
    public class BlockType1 extends SpinBlock{
    
    	public BlockType1 (int x, int y) {
    		// TODO Auto-generated constructor stub
    		super(x,y);
    		double gain = 0.7;
    		double feedback = 0.24;
    		name = "BlockType1";
    		
    		addParam("Gain", gain);
    		addParam("Feedback", feedback);
    	}
    }
    Java Code:
    public class BlockType2 extends SpinBlock{
    
    	public BlockType2 (int x, int y) {
    		// TODO Auto-generated constructor stub
    		super(x, y);
    		double parameter1 = 0.234214;
    		double parameter2 = 0.12313;
    		name = "BlockType2";
    		addParam("Parameter1", parameter1);
    		addParam("Parameter2", parameter2);
    
    	}
    
    }
    As you can see, the SpinBlock class holds the attributes name, x_pos and y_pos. The derived classes use these attributes as well as adding their own, whose name and number are not known except to their classes. I decided to use a Map to hold these extra attributes so that the classes could save and retrieve them by name. However the file save and load routines only need to know "what are all the extra attributes, i.e. what are their names and values"? I'm sure this is easy but I can't seem to get my head around it.

    Here's my file class, with save and load routines:

    Java Code:
    import java.io.FileNotFoundException;
    import java.io.FileReader;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.util.Iterator;
    import java.util.Map;
    
    import org.json.JSONException;
    
    import com.google.gson.Gson;
    import com.google.gson.GsonBuilder;
    import com.google.gson.JsonArray;
    import com.google.gson.JsonElement;
    import com.google.gson.JsonObject;
    import com.google.gson.JsonParser;
    
    public class SpinFile {
    
    	public SpinFile() {
    		// TODO Auto-generated constructor stub
    	}
    	
    	public static void fileReadJSON(SpinModel m, String fileName) throws JSONException {
    		JsonParser parser = new JsonParser();
    		try {
    
    			Object obj = parser.parse(new FileReader(fileName));
    
    			JsonObject jsonObject = (JsonObject) obj;
    
    			JsonElement name = jsonObject.get("Company");
    			System.out.println(name);
    			name = jsonObject.get("Application");
    			System.out.println(name);
    			name = jsonObject.get("Version");
    			System.out.println(name);
    			name = jsonObject.get("Patch");
    			System.out.println(name);
    			name = jsonObject.get("Model");
    			System.out.println(name);
    
    			JsonArray blocks = (JsonArray) jsonObject.get("Blocks");
    			int nItems = blocks.size();
    
    			for (int i = 0; i < nItems; i++) {
    
    				JsonObject obj2 = (JsonObject)blocks.get(i); 
    				JsonElement blockName = obj2.get("Name");
    				JsonElement x = obj2.get("x");
    				JsonElement y = obj2.get("y");
    				SpinBlock pcB = null;
    				switch (blockName.getAsString()) {
    
    				case "BlockType1":
    					pcB = new BlockType1(x.getAsInt(), y.getAsInt());				
    					break;
    				case "BlockType2":
    					pcB = new BlockType2(x.getAsInt(), y.getAsInt());				
    					break;
    				default:
    					break;
    				}	
    				m.addBlock(pcB);
    			}	
    		} catch (FileNotFoundException e) {
    			e.printStackTrace();
    		}
    
    	} 
    
    	
    	public void fileSaveJSON(SpinModel m, String fileName) throws JSONException {
    
    		// Gson gs = new Gson();
    		Gson gs = new GsonBuilder().setPrettyPrinting().create();
    
    		JsonObject obj = new JsonObject();
    
    		System.out.printf("\n\nFile save in progress...\n");
    
    		obj.addProperty("Company", "My Company");
    		obj.addProperty("Application", "My Application");
    		obj.addProperty("Version", "0.6");
    		obj.addProperty("Patch", "Patch Name");
    
    		Iterator<SpinBlock> itr = m.blockList.iterator();
    		SpinBlock block;
    
    		JsonObject obj2 = null;
    		JsonArray blockArray = new JsonArray();
    		
    		while(itr.hasNext()) {
    			block = itr.next();
    			obj2 = new JsonObject(); 
    			obj2.addProperty("Name", block.getName());
    			obj2.addProperty("x", block.getX());
    			obj2.addProperty("y", block.getY());	
    			// this is where things start to get screwy
    			Map<String, Double> Zparams = block.getParams();
    			obj2.addProperty("Params", gs.toJson(Zparams));
    			blockArray.add(obj2);	
    		}		
    	
    		obj.add("Blocks", blockArray);
    		
    		System.out.println(obj);
    		
    		try {
    
    			FileWriter file = new FileWriter(fileName);
    			file.write(obj.toString());
    			file.flush();
    			file.close();
    
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    
    		System.out.println("File saved!");
    
    	}
    }
    and to round it out, here's the SpinModel class and the main JavaTest class:

    Java Code:
    
    import java.util.ArrayList;
    
    public class SpinModel {
    
    	String name = "SpinModel";
    	ArrayList<SpinBlock> blockList = null;
    	boolean changed = false;
    	static int nBlocks = 0;
    
    	public SpinModel() {
    		// TODO Auto-generated constructor stub
    		// super();
    		newModel();
    	}
    
    	// newModel() clears out the current list
    	public void newModel() {
    		nBlocks = 0;
    		blockList = new ArrayList<SpinBlock>();
    		changed = false;
    	}
    
    	public int addBlock(SpinBlock pCB) {
    		nBlocks++;
    		blockList.add(pCB);
    		changed = true;
    		return 0;
    	}
    }
    Java Code:
    import org.json.JSONException;
    
    
    public class JavaTest {
    
    	public JavaTest() {
    		// TODO Auto-generated constructor stub
    	}
    
    	/**
    	 * @param args
    	 * @throws JSONException 
    	 */
    	public static void main(String[] args) throws JSONException {
    		// TODO Auto-generated method stub
    		SpinModel m = new SpinModel();
    		m.addBlock(new BlockType1(40, 60));
    		m.addBlock(new BlockType2(50, 90));
    		
    		SpinFile f = new SpinFile();
    		f.fileSaveJSON(m, "c:\\temp\\file.txt");
    		
    		m.newModel();
    		f.fileReadJSON(m, "c:\\temp\\file.txt");
    	}
    }
    As it stands, the code can write and read the attributes which are part of the SpinBlock class, but I am having a real hard time figuring out how to put the attributes which are kept in the Map into a form where the key and value can be extracted and used to form name/value pairs that I can write out with JSON as I am doing for the name, x_pos and y_pos.

    PS I looked at JSON.Simple, JSON, and Gson, each with some possibly useful features, but ended up more confused than anything else.

    Thanks for any insight!

    DL
    Last edited by Digital Larry; 04-12-2013 at 05:37 PM.

  2. #2
    JosAH's Avatar
    JosAH is offline Moderator
    Join Date
    Sep 2008
    Location
    Voorschoten, the Netherlands
    Posts
    13,526
    Blog Entries
    7
    Rep Power
    20

    Default Re: Stumped by Json, file I/O, extended class

    Do you really have to use Json for this? Simple Serialization can handle the job easily ...

    kind regards,

    Jos
    cenosillicaphobia: the fear for an empty beer glass

  3. #3
    Digital Larry is offline Member
    Join Date
    Mar 2013
    Posts
    57
    Rep Power
    0

    Default Re: Stumped by Json, file I/O, extended class

    Ah regarding JSON, some guy who had no idea what I was doing suggested it instead of XML. So let's look at serialization.

    Here's all my code. It runs, and the save does seem to save something. The read reads something but when I try to access the model, there's nothing there.

    Now maybe I need to serialize it at some lower level. I tried using the entire model.

    Ah... looks like Map is not serializable?

    http://docs.oracle.com/javase/6/docs.../util/Map.html

    Java Code:
    public class JavaTest {
    
    	public JavaTest() {
    		// TODO Auto-generated constructor stub
    	}
    
    	/**
    	 * @param args
    	 * @throws JSONException 
    	 */
    	public static void main(String[] args) throws JSONException {
    		// TODO Auto-generated method stub
    		SpinModel m = new SpinModel();
    		m.addBlock(new BlockType1(40, 60));
    		m.addBlock(new BlockType2(50, 90));
    		
    		SpinFile f = new SpinFile();
    		f.fileSave(m, "c:\\temp\\file.txt");
    		
    		m.newModel();
    		f.fileRead(m, "c:\\temp\\file.txt");
    		System.out.println(m);
    		
    		m.forEachBlock();
    	}
    }
    Java Code:
    import java.io.Serializable;
    import java.util.ArrayList;
    import java.util.Iterator;
    
    
    
    public class SpinModel implements Serializable {
    
    	String name = "SpinModel";
    	ArrayList<SpinBlock> blockList = new ArrayList<SpinBlock>();
    	boolean changed = false;
    	static int nBlocks = 0;
    
    	public SpinModel() {
    		// TODO Auto-generated constructor stub
    		// super();
    		newModel();
    	}
    
    	// newModel() clears out the current list
    	public void newModel() {
    		nBlocks = 0;
    		blockList = new ArrayList<SpinBlock>();
    		changed = false;
    	}
    
    	public int addBlock(SpinBlock pCB) {
    		nBlocks++;
    		blockList.add(pCB);
    		changed = true;
    		return 0;
    	}
    	
    	public int forEachBlock() {
    		SpinBlock block = null;
    		Iterator<SpinBlock> itr = blockList.iterator();
    		while (itr.hasNext()) {
    			block = itr.next();
    			System.out.println(block.getName() + " " + block.getX() + " " + block.getY());
    			// now blockMin is the block with the lowest number
    		}
    		return 0;
    	}
    
    }
    Java Code:
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.FileReader;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.util.Iterator;
    import java.util.Map;
    
    public class SpinFile {
    
    	public SpinFile() {
    		// TODO Auto-generated constructor stub
    	}
    
    	public static void fileSave(SpinModel m, String fileName) {
    		try { 
    			FileOutputStream fos = new FileOutputStream(fileName); 
    			ObjectOutputStream oos = new ObjectOutputStream(fos); 
    			oos.writeObject(m); 
    			oos.flush(); 
    			oos.close(); 
    		} 
    		catch(Exception e) { 
    			System.out.println("Exception during serialization: " + e); 
    			//		System.exit(0); 
    		} 
    	}
    
    	public static void fileRead(SpinModel m, String fileName) {
    		// Object deserialization 
    		try { 
    			FileInputStream fis = new FileInputStream(fileName); 
    			ObjectInputStream ois = new ObjectInputStream(fis); 
    			m = (SpinModel)ois.readObject(); 
    			ois.close(); 
    			System.out.println("m: " + m); 
    		} 
    		catch(Exception e) { 
    			System.out.println("Exception during deserialization: " + 
    					e); 
    			System.exit(0); 
    		} 
    	} 	
    }
    Java Code:
    import java.io.Serializable;
    
    
    public class BlockType1 extends SpinBlock  {
    
    	/**
    	 * 
    	 */
    	private static final long serialVersionUID = 1L;
    
    	public BlockType1 (int x, int y)  {
    		// TODO Auto-generated constructor stub
    		super(x,y);
    		double gain = 0.7;
    		double feedback = 0.24;
    		name = "BlockType1";
    		
    		addParam("Gain", gain);
    		addParam("Feedback", feedback);
    	}
    }
    Java Code:
    import java.io.Serializable;
    import java.util.HashMap;
    import java.util.Map;
    
    public class SpinBlock implements Serializable {
    	
    	// position and size of the enclosing rectangle
    	String name = "Default";
    	int x_pos = 0;
    	int y_pos = 0;
    
    	protected Map<String, Double> params = new HashMap<String, Double>();
    
    	public SpinBlock(int x, int y) {
    		// TODO Auto-generated constructor stub
    		x_pos = x;
    		y_pos = y;
    	}
    
    	public Map<String, Double> getParams() {
    		return params;
    	}
    
    	public String getName() {
    		// TODO Auto-generated method stub
    		return name;
    	}
    
    	public int getX() {
    		// TODO Auto-generated method stub
    		return x_pos;
    	}
    
    	public int getY() {
    		// TODO Auto-generated method stub
    		return y_pos;
    	}
    	
    	public void addParam(String s, double d) {
    		params.put(s,d);
    	}
    
    }
    Java Code:
    public class BlockType2 extends SpinBlock{
    
    	public BlockType2 (int x, int y) {
    		// TODO Auto-generated constructor stub
    		super(x, y);
    		double parameter1 = 0.234214;
    		double parameter2 = 0.12313;
    		name = "BlockType2";
    		addParam("Parameter1", parameter1);
    		addParam("Parameter2", parameter2);
    
    	}
    
    }
    Last edited by Digital Larry; 04-13-2013 at 02:12 AM.

  4. #4
    Digital Larry is offline Member
    Join Date
    Mar 2013
    Posts
    57
    Rep Power
    0

    Default Re: Stumped by Json, file I/O, extended class

    Looks like I made a little boo boo!

    Works way better with these changes. Thanks for the suggestion on serialization! Dang self-taught programmers (like me)!

    Java Code:
    import java.io.FileInputStream;
    
    public class SpinFile {
    
    	public SpinFile() {
    		// TODO Auto-generated constructor stub
    	}
    
    	public static void fileSave(SpinModel m, String fileName) {
    		try { 
    			FileOutputStream fos = new FileOutputStream(fileName); 
    			ObjectOutputStream oos = new ObjectOutputStream(fos); 
    			oos.writeObject(m); 
    			oos.flush(); 
    			oos.close(); 
    		} 
    		catch(Exception e) { 
    			System.out.println("Exception during serialization: " + e); 
    			//		System.exit(0); 
    		} 
    	}
    
    	public static SpinModel fileRead(SpinModel m, String fileName) {
    		// Object deserialization 
    		try { 
    			FileInputStream fis = new FileInputStream(fileName); 
    			ObjectInputStream ois = new ObjectInputStream(fis); 
    			m = (SpinModel)ois.readObject(); 
    			ois.close(); 
    			System.out.println("m: " + m); 
    		} 
    		catch(Exception e) { 
    			System.out.println("Exception during deserialization: " + 
    					e); 
    			System.exit(0); 
    		} 
    		return m;
    	} 	
    }
    Java Code:
    import org.json.JSONException;
    
    public class JavaTest {
    
    	public JavaTest() {
    		// TODO Auto-generated constructor stub
    	}
    
    	/**
    	 * @param args
    	 * @throws JSONException 
    	 */
    	public static void main(String[] args) throws JSONException {
    		// TODO Auto-generated method stub
    		SpinModel m = new SpinModel();
    		m.addBlock(new BlockType1(40, 60));
    		m.addBlock(new BlockType2(50, 90));
    		
    		SpinFile f = new SpinFile();
    		f.fileSave(m, "c:\\temp\\file.txt");
    		
    		m.newModel();
    		m = f.fileRead(m, "c:\\temp\\file.txt");
    		System.out.println(m);
    		
    		m.forEachBlock();
    	}
    }

  5. #5
    Tolls is offline Moderator
    Join Date
    Apr 2009
    Posts
    12,014
    Rep Power
    20

    Default Re: Stumped by Json, file I/O, extended class

    Can I ask why the parent Block class is holding a Map of attributes related to the subclasses?
    Why not simply give the subclasses their own attributes? That's what inheritance is for...

    Also, for the serialisation part, there is no need to pass the SpinModel in. Since that's the reason you had a problem initially (Java is pass by value), it's actually been detrimental.
    Please do not ask for code as refusal often offends.

    ** This space for rent **

  6. #6
    Digital Larry is offline Member
    Join Date
    Mar 2013
    Posts
    57
    Rep Power
    0

    Default Re: Stumped by Json, file I/O, extended class

    Answers to "why" questions about my code are always a little embarrassing.

    Yes, you noticed that I don't use the Map directly in the parent subclass. I was thinking at one point of holding ALL parameters in the Map, even the ones defined in the parent class (Name, x, and y). After I got the serialization working I just didn't bother to clean that part out.

    Your point about passing the SpinModel in is also well taken. Since I am self taught by brute force in Java and have not been following any specific path for learning, other than trying to get my one project working, I've apparently developed some bad habits. And that's another reason it helps to post things here in spite of the humiliation

    Thanks again!

    DL

  7. #7
    Tolls is offline Moderator
    Join Date
    Apr 2009
    Posts
    12,014
    Rep Power
    20

    Default Re: Stumped by Json, file I/O, extended class

    We all have to learn somewhere...
    Please do not ask for code as refusal often offends.

    ** This space for rent **

  8. #8
    Digital Larry is offline Member
    Join Date
    Mar 2013
    Posts
    57
    Rep Power
    0

    Default Re: Stumped by Json, file I/O, extended class

    OK here's another question... as I've been developing my program, and adding new blocks, occasionally I get to a point where it refuses to load a file created with an earlier version. Well it doesn't actually refuse, it crashes with a serialization exception. As time goes on I know absolutely that I will be adding new functional blocks to the program. Up to now I've been using auto-generated serialization IDs. Is there any way to preserve backwards file compatibility?

  9. #9
    Tolls is offline Moderator
    Join Date
    Apr 2009
    Posts
    12,014
    Rep Power
    20

    Default Re: Stumped by Json, file I/O, extended class

    If you're adding attributes to existing block classes (that's what you store, isn't it?) then you need to use a proper versioning system.
    By "proper" I mean, start at 1 and increment.
    Serialisation can handle adding attributes if the versioning is done correctly...though you'd probably better double check on that as I'm working from memory here (nearly home time).
    In fact, here's the horses mouth.
    Type Changes Affecting Serialisation.
    Please do not ask for code as refusal often offends.

    ** This space for rent **

  10. #10
    Digital Larry is offline Member
    Join Date
    Mar 2013
    Posts
    57
    Rep Power
    0

    Default Re: Stumped by Json, file I/O, extended class

    Most illuminating response! Thanks!

Similar Threads

  1. @RunWith(Parameterized.class) extended class error
    By Richard3 in forum New To Java
    Replies: 5
    Last Post: 01-31-2012, 02:47 PM
  2. Replies: 1
    Last Post: 07-21-2011, 10:46 PM
  3. Extended Class - Cannot Find Symbol
    By javak in forum New To Java
    Replies: 15
    Last Post: 02-27-2011, 04:43 PM
  4. Replies: 0
    Last Post: 04-15-2010, 12:00 PM
  5. Returned type changes if class is extended. How?
    By Gelembjuk in forum New To Java
    Replies: 10
    Last Post: 10-31-2008, 11:18 AM

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •