Skip to content

Latest commit

 

History

History
 
 

invoice

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 

JSONx Sample: Invoice

JSON Schema for the enterprise

Build Status Coverage Status Javadocs Released Version Snapshot Version

Abstract

This document presents the Invoice sample application.

Table of Contents

  1 Invoice
  2 Contributing
  3 License

1 Invoice

This sample is an introduction to the following JSONx technologies:

  1. JSON Schema Definition Language (JSD).
  2. JSONx Binding API.

The following illustrates usage of the binding API with an example of an invoice.

  1. Create invoice.jsd or invoice.jsdx in src/main/resources/:

JSD
{
  "jx:ns": "http://www.jsonx.org/schema-0.3.jsd",
  "jx:schemaLocation": "http://www.jsonx.org/schema-0.3.jsd http://www.jsonx.org/schema.jsd",

  "money": { "jx:type": "number", "range": "[0,]", "scale": 2},
  "positiveInteger": { "jx:type": "number", "range": "[1,]", "scale": 0},
  "date": { "jx:type": "string", "pattern": "-?\\d{4}-((0[13578]|1[02])-(0[1-9]|[12]\\d|3[01])|(02-(0[1-9]|1\\d|2\\d))|((0[469]|11)-(0[1-9]|[12]\\d|30)))" },
  "nonEmptyString": { "jx:type": "string", "pattern": "\\S|\\S.*\\S" },
  "address": { "jx:type": "object", "properties": {
    "name": { "jx:type": "reference", "nullable": false, "type": "nonEmptyString" },
    "address": { "jx:type": "reference", "nullable": false, "type": "nonEmptyString" },
    "city": { "jx:type": "reference", "nullable": false, "type": "nonEmptyString" },
    "postalCode": { "jx:type": "reference", "nullable": false, "type": "nonEmptyString", "use": "optional" },
    "country": { "jx:type": "reference", "type": "nonEmptyString" } }
  },
  "invoice": { "jx:type": "object", "properties": {
    "number": { "jx:type": "reference", "type": "positiveInteger" },
    "date": { "jx:type": "reference", "type": "date" },
    "billingAddress": { "jx:type": "reference", "type": "address" },
    "shippingAddress": { "jx:type": "reference", "type": "address" },
    "billedItems": { "jx:type": "array", "nullable": false, "elements": [
      { "jx:type": "reference", "type": "item" } ] } }
  },
  "item": { "jx:type": "object", "properties": {
    "description": { "jx:type": "reference", "nullable": false, "type": "nonEmptyString" },
    "code": { "jx:type": "reference", "nullable": false, "type": "positiveInteger" },
    "quantity": { "jx:type": "reference", "nullable": false, "type": "positiveInteger" },
    "price": { "jx:type": "reference", "nullable": false, "type": "money" } }
  }
}
JSDx
<schema
  xmlns="http://www.jsonx.org/schema-0.3.xsd"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.jsonx.org/schema-0.3.xsd http://www.jsonx.org/schema.xsd">

  <number name="money" range="[0,]" scale="2"/>
  <number name="positiveInteger" range="[1,]" scale="0"/>
  <string name="date" pattern="-?\d{4}-((0[13578]|1[02])-(0[1-9]|[12]\d|3[01])|(02-(0[1-9]|1\d|2\d))|((0[469]|11)-(0[1-9]|[12]\d|30)))"/>
  <string name="nonEmptyString" pattern="\S|\S.*\S"/>
  <object name="address">
    <property name="name" xsi:type="reference" type="nonEmptyString" nullable="false"/>
    <property name="address" xsi:type="reference" type="nonEmptyString" nullable="false"/>
    <property name="city" xsi:type="reference" type="nonEmptyString" nullable="false"/>
    <property name="postalCode" xsi:type="reference" type="nonEmptyString" nullable="false" use="optional"/>
    <property name="country" xsi:type="reference" type="nonEmptyString"/>
  </object>
  <object name="invoice">
    <property name="number" xsi:type="reference" type="positiveInteger"/>
    <property name="date" xsi:type="reference" type="date"/>
    <property name="billingAddress" xsi:type="reference" type="address"/>
    <property name="shippingAddress" xsi:type="reference" type="address"/>
    <property name="billedItems" xsi:type="array" nullable="false">
      <reference type="item"/>
    </property>
  </object>
  <object name="item">
    <property name="description" xsi:type="reference" type="nonEmptyString" nullable="false"/>
    <property name="code" xsi:type="reference" type="positiveInteger" nullable="false"/>
    <property name="quantity" xsi:type="reference" type="positiveInteger" nullable="false"/>
    <property name="price" xsi:type="reference" type="money" nullable="false"/>
  </object>

</schema>

Note: You can use the Converter utility to automatically convert between JSD and JSDx.

  2. With the invoice.jsd or invoice.jsdx, you can use the jsonx-maven-plugin to automatically generate the Java class files. In your POM, add:

<plugin>
  <groupId>org.jsonx</groupId>
  <artifactId>jsonx-maven-plugin</artifactId>
  <version>0.3.2</version>
  <executions>
    <execution>
      <goals>
        <goal>generate</goal>
      </goals>
      <phase>generate-sources</phase>
      <configuration>
        <destDir>${project.build.directory}/generated-sources/jsonx</destDir>
        <prefix>com.example.invoice.</prefix>
        <schemas>
          <schema>src/main/resources/invoice.jsd</schema> <!-- or invoice.jsdx -->
        </schemas>
      </configuration>
    </execution>
  </executions>
</plugin>

  3. (Alternatively) Create the Java class files by hand:

Note: Set-ters and get-ters have been replaced with public fields for conciseness.

import org.jsonx.*;

public class Address implements JxObject {
  @StringProperty(pattern="\\S|\\S.*\\S", nullable=false)
  public String name;

  @StringProperty(pattern="\\S|\\S.*\\S", nullable=false)
  public String address;

  @StringProperty(pattern="\\S|\\S.*\\S", nullable=false)
  public String city;

  @StringProperty(pattern="\\S|\\S.*\\S", use=Use.OPTIONAL, nullable=false)
  public String postalCode;

  @StringProperty(pattern="\\S|\\S.*\\S")
  public String country;
}
import org.jsonx.*;

public class Item implements JxObject {
  @StringProperty(pattern="\\S|\\S.*\\S", nullable=false)
  public String description;

  @NumberProperty(range="[1,]", scale=0, nullable=false)
  public java.math.BigInteger code;

  @NumberProperty(range="[1,]", scale=0, nullable=false)
  public java.math.BigInteger quantity;

  @NumberProperty(range="[1,]", scale=2, nullable=false)
  public java.math.BigDecimal price;
 }
import org.jsonx.*;

public class Invoice implements JxObject {
  @NumberProperty(range="[1,]", scale=0)
  public java.math.BigInteger number;

  @StringProperty(pattern="-?\\d{4}-((0[13578]|1[02])-(0[1-9]|[12]\\d|3[01])|(02-(0[1-9]|1\\d|2\\d))|((0[469]|11)-(0[1-9]|[12]\\d|30)))")
  public String date;

  @ObjectProperty
  public Address billingAddress;

  @ObjectProperty
  public Address shippingAddress;

  @ObjectElement(id=0, type=Item.class)
  @ArrayProperty(elementIds={0}, nullable=false)
  public java.util.List<Item> billedItems;
}

  4. You can use these classes to represent Addresses, Items, and Invoices.

Address address = new Address();
address.name = "John Doe";
address.address = "111 Wall St.";
address.city = "New York";
address.postalCode = "10043";
address.country = "USA";

Item item = new Item();
item.code = BigInteger.valueOf(123);
item.description = "Pocket Protector";
item.price = new BigDecimal("14.99");
item.quantity = BigInteger.valueOf(5);

Invoice invoice = new Invoice();
invoice.number = BigInteger.valueOf(14738);
invoice.date = "2019-05-13";
invoice.billingAddress = address;
invoice.shippingAddress = address;
invoice.billedItems = Collections.singletonList(item);

  5. You can now marshal the Java objects to JSON:

String json = JxEncoder._2.marshal(invoice);
System.out.println(json);

... will produce:

{
  "number": 14738,
  "date": "2019-05-13",
  "billingAddress": {
    "name": "John Doe",
    "address": "111 Wall St.",
    "city": "New York",
    "postalCode": "10043",
    "country": "USA"
  },
  "shippingAddress": {
    "name": "John Doe",
    "address": "111 Wall St.",
    "city": "New York",
    "postalCode": "10043",
    "country": "USA"
  },
  "billedItems": [{
    "description": "Pocket Protector",
    "code": 123,
    "quantity": 5,
    "price": 14.99
  }]
}

  6. You can also parse the JSON into Java objects:

Invoice invoice2 = JxDecoder.parseObject(Invoice.class, json);
assertEquals(invoice, invoice2);

The code included in this module implements this example.

2 Contributing

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.

Please make sure to update tests as appropriate.

3 License

This project is licensed under the MIT License - see the LICENSE.txt file for details.