list of dots Digital Research Alliance of Canada logo  NSERC logo  University of Ottawa logo / UniversitĂ© d'Ottawa

User Manual    [Previous]   [Next]   

JSON

JSON as a data-interchange format widely used to save and load data in many contexts and languages. It can be used in transmitting over networks. and saving the state of the system persistently.

Umple provides a capability to generate a Json representation of instances of any Umple class, including the complete network of all associated (linked) objects, as well as to reload objects that have been saved. This currently only works with the Java generator for Umple.

 

To generate functions for serializing and deserializing Json in Umple Java code, specify the suboption "genJson" using the command line or UmpleOnline. A suitable command line would be: umple [FILENAME].ump -g Java -s genJson -c- ... this will generated the needed functions and also compile the code.

When specifying the suboption genJson, all generated Java classes will have the following functions as part of their API:

  • String toJson(). This method generates (serializes) a Json representation of a given object, and all objects connected to it by associations.
  • Object fromJson(String) This is a static method that instantiates (deserialize) all the objects that had been saved using toJson. Data stored that represents attributes, associations and the current states of state machines is restored.

For each state machine, the Json holds the current state under the name of the state machine, and each nested region is stored the same way under its own name, for example "status" : "Paid" and "statusPaid" : "ReadyToShip". When an object is reloaded, its states are set directly: no entry actions or do activities run, because the object is being restored rather than changing state. Timed transitions of the restored states start again with their full delay. Queued and pooled state machines take events as before, but events still waiting in their queue when the Json was generated are not saved, so they start with an empty queue. A state name that the state machine does not have makes fromJson throw an IllegalArgumentException, for the reloaded object and for the objects associated with it. A state missing from the Json (for example in Json saved before state machines were stored) gets the value it has in a new object, without taking automatic transitions, so a nested region is Null unless its enclosing states are start states: "status" : "Paid" without "statusPaid" leaves statusPaid Null. Keep every state field when editing saved Json. History states are not saved, so after reloading they start as they do in a new object.

External tools such as GSON can also be used to serialize and deserialize object data, but these tools do not support circular references. An attempt to save data with circular references in GSON will result in the code crashing with an infinite recursion error. A circular reference occurs when one object points to a second object, and the second object points back (possibly indirectly) to the first. Circular references are inherent in the code generated by Umple bidirectional associations and allow very useful and efficient APIs to be present in generated Umple code. Umple's builtin Json generation handles these circular references in persisted Json data by attaching an umpleObjectID to each saved object. When the date is re-loaded into Umple, these umpleObjectID codes are used to ensure that the circular references are regenerated correctly.

 

Examples: These demonstrate how use toJson() and fromJson() to serialize and de-serialize Json.

 

This example shows a simple class implementing JSON Serialization

suboption "genJson";
class Bank {
  String bankName;
  int numAccount;
  
  public static void main(String[] args) Java{
    Bank boc=new Bank("BankCanada",100000);
    System.out.println(boc.toJson());
  }
}
// @@@skipcompile   Temporary to bootstrap
      

Load the above code into classic UmpleOnline
Load the above code into UmpleOnline V2

 

This example shows a more sophisticated model implementing JSON serialization and deserialization; it generates and outputs the Json, then reloads it, then outputs it again. The results are the same, except for the UmpleObjectIDs.

suboption "genJson";
class University {
  singleton;
  lazy name;
  lazy Float tuition;
  1 -- * Course;
}

class Person {
  Integer id;
  name;
}

class Student {
  isA Person;
  Float tuitionPaid;
}

class PartTimeStudent {
  isA Student;
  Boolean isExemptFromFees;
}

class Employee {
  isA Person;
  Double salary;
  lazy job;
  * -- * CourseSection teaches;
}

association {
  * Student -- 1 University;
}

class Course {
  title;
}

class CourseSection {
  code;
  * -- 1 Course;
}

associationClass Registration {
  * Student;
  * CourseSection;
  lazy grade;
}

class University {
  public static void main (String[] args) Java{
  
    University u = new University();
    u.setName("UOttawa");
    u.setTuition(1000.00f);
  
    Student s1 = new Student(101, "Tim", 800.0f, u);
    Student s2 = new Student(102, "Jane", 2000.0f, u); 
    Student s3 = new Student(103, "Ali", 750.0f, u); 
  
    PartTimeStudent s4= new PartTimeStudent(104, "Marie", 600.56f, u, false);
  
    Employee e1 = new Employee(202, "Julia", 6585.45);
    Employee e2 = new Employee(203, "Robin", 8785.11);
    e2.setJob("Advisor");
  
    Course ca= new Course("Architecture",u);
    Course cb= new Course("Biology",u);
CourseSection csa1= new CourseSection("A1",ca);
    e1.addTeache(csa1);
    CourseSection csa2= new CourseSection("A2",ca);
    e1.addTeache(csa1);
    CourseSection csb1= new CourseSection("B1",cb);
    e2.addTeache(csa1);
    e1.addTeache(csa1);  // two teachers for this

    new Registration(s1,csa1);
    new Registration(s1,csb1);
    new Registration(s2,csa2);
    new Registration(s2,csb1);
    new Registration(s2,csa1);
    new Registration(s3,csb1);
    new Registration(s4,csa2);
    String jsonString = u.toJson();
    University u2 = University.fromJson(jsonString);
    
    System.out.println("----- fromJson object -------\n"+u2);
    
    System.out.println("----- fromJson --->  toJson ------");
    System.out.println(u2.toJson());
    
  }
}
// @@@skipcompile   Temporary to bootstrap
  
      

Load the above code into classic UmpleOnline
Load the above code into UmpleOnline V2

 

This example shows an object with a nested state machine being saved and reloaded; the reloaded object continues from the state it was saved in.

suboption "genJson";
class Order {
  String orderId;
  status {
    Placed {
      pay -> Paid;
    }
    Paid {
      ship -> Shipping;
      Packing { pack -> ReadyToShip; }
      ReadyToShip {}
    }
    Shipping {}
  }

  public static void main(String[] args) Java{
    Order order = new Order("A-17");
    order.pay();
    order.pack();
    String jsonString = order.toJson();
    System.out.println(jsonString);

    // The reloaded order is in Paid.ReadyToShip and continues from there
    Order reloaded = Order.fromJson(jsonString);
    System.out.println(reloaded.getStatusFullName());
    reloaded.ship();
    System.out.println(reloaded.getStatusFullName());
  }
}

      

Load the above code into classic UmpleOnline
Load the above code into UmpleOnline V2