Concise dynamic object creation syntax for JSON coding

Gosu supports a concise object creation syntax similar to JSON directly in its grammar. The following Gosu features provide this functionality:

  • You can omit the type name in a new expression if Gosu can infer the type. For example, instead of typing new TestClass(arg1, arg2), you can type new(arg1, arg2). The programming context already assumes the compile-time type called TestClass.
  • You can initialize fields during instantiation using a special syntax with curly braces around a comma-delimited list of property assignments, with a colon before the property name. For example:
    new TestClass() { :Name = "John Smith" }
  • Gosu supports dynamic non-type-safe access to properties and methods for variables of the type called dynamic.Dynamic. No declaration of specific property names or method names is required in advance. For programming contexts of type dynamic.Dynamic, a newly instantiated object assumes the default run-time type of Expando. The Expando class implements the Bindings interface. Gosu adds enhancement methods to this class to convert to JSON (toJson), XML (toXml), or Gosu object initialization code (toGosu).

When you combine these features, you can create objects with multiple types of data without declaring any specific structure in advance, and can convert to other formats as needed.

The following Gosu code creates a dynamic complex object and prints it in JSON syntax, XML syntax, and Gosu object initialization syntax:

var person: dynamic.Dynamic

person = new() {
  :Name = "John Smith",
  :Age = 39,
  :Address = new() {
    :Number = 123,
    :Street = "Main St.",
    :City = "Foster City",
    :State = "CA"
  },
  :Hobby = {
    new() {
      :Category = "Sport",
      :Name = "Swimming"
    },
    new() {
      :Category = "Recreation",
      :Name = "Hiking"
    }
  }
}

print("**** To JSON:")
print(person.toJson())

print("**** To XML:")
print(person.toXml())

print("**** To Gosu:")
print(person.toGosu())

This example prints the following:

**** To JSON:
{
  "Name": "John Smith",
  "Age": 39,
  "Address": {
    "Number": 123,
    "Street": "Main St.",
    "City": "Foster City",
    "State": "CA"
  },
  "Hobby": [
    {
      "Category": "Sport",
      "Name": "Swimming"
    },
    {
      "Category": "Recreation",
      "Name": "Hiking"
    }
  ]
}
**** To XML:
<object>
  <Name>John Smith</Name>
  <Age>39</Age>
  <Address>
    <Number>123</Number>
    <Street>Main St.</Street>
    <City>Foster City</City>
    <State>CA</State>
  </Address>
  <Hobby>
    <li>
      <Category>Sport</Category>
      <Name>Swimming</Name>
    </li>
    <li>
      <Category>Recreation</Category>
      <Name>Hiking</Name>
    </li>
  </Hobby>
</object>
**** To Gosu:
new Dynamic() {
  :Name = "John Smith",
  :Age = 39,
  :Address = new() {
    :Number = 123,
    :Street = "Main St.",
    :City = "Foster City",
    :State = "CA"
  },
  :Hobby = {
    new() {
      :Category = "Sport",
      :Name = "Swimming"
    },
    new() {
      :Category = "Recreation",
      :Name = "Hiking"
    }
  }
}

Note that for the Gosu initializer syntax serialization, you can evaluate the String data at run time to create a Gosu object:

var clone = eval( person.toGosu() )

See also