Search code examples
javajsonavalara

Avalara: What is a "DateTime" valid format for the json date?


What is the correct JSON date format for Avalara? The following code:

 TransactionModel transaction = new TransactionBuilder(client, "COMPANY", DocumentType.SalesOrder, "myCompany.")
    .withDate(Calendar.getInstance().getTime())
    .withAddress(TransactionAddressType.SingleLocation, null, null, null, null, null, zipCode, "US")
    .withLine( new BigDecimal(100.0), new BigDecimal(1), "P0000000")
    .Create();

throws an exception that does not indicate the correct format:

com.google.gson.JsonSyntaxException: 2019-10-01
    at com.google.gson.DefaultDateTypeAdapter.deserializeToDate(DefaultDateTypeAdapter.java:107)
    at com.google.gson.DefaultDateTypeAdapter.deserialize(DefaultDateTypeAdapter.java:82)
    at com.google.gson.DefaultDateTypeAdapter.deserialize(DefaultDateTypeAdapter.java:35)
    at com.google.gson.TreeTypeAdapter.read(TreeTypeAdapter.java:58)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:93)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:172)
    at com.google.gson.Gson.fromJson(Gson.java:803)
    at com.google.gson.Gson.fromJson(Gson.java:768)
    at com.google.gson.Gson.fromJson(Gson.java:717)
    at net.avalara.avatax.rest.client.serializer.JsonSerializer.DeserializeObject(JsonSerializer.java:15)
    at net.avalara.avatax.rest.client.RestCall.call(RestCall.java:99)
    at net.avalara.avatax.rest.client.AvaTaxClient.createTransaction(AvaTaxClient.java:19174)
    at net.avalara.avatax.rest.client.TransactionBuilder.Create(TransactionBuilder.java:425)

Solution

  • When in doubt, read the source. It looks like com.google.gson.DefaultDateTypeAdapter has a couple default date formats that it will try to use in deserializeToDate. So make sure you are using one of those.

    Most of the date formats are coming from java.text.DateFormat

    Also check the source of AvaTax-REST-V2

    If you have the source linked in your editor, then I recommend putting a breakpoint at a few places in the stack trace to see what's happening. One good candidate would be in deserializeToDate of course.


    DefaultDateTypeAdapter.java

    /**
     * List of 1 or more different date formats used for de-serialization attempts. The first of them is
     * used for serialization as well.
     */
    private final List<DateFormat> dateFormats = new ArrayList<DateFormat>();
    
    DefaultDateTypeAdapter(Class<? extends Date> dateType) {
        this.dateType = verifyDateType(dateType);
        dateFormats.add(DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.US));
        if (!Locale.getDefault().equals(Locale.US)) {
            dateFormats.add(DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT));
        }
        if (JavaVersion.isJava9OrLater()) {
            dateFormats.add(PreJava9DateFormatProvider.getUSDateTimeFormat(DateFormat.DEFAULT, DateFormat.DEFAULT));
        }
    }
    
    DefaultDateTypeAdapter(Class<? extends Date> dateType, String datePattern) {
        this.dateType = verifyDateType(dateType);
        dateFormats.add(new SimpleDateFormat(datePattern, Locale.US));
        if (!Locale.getDefault().equals(Locale.US)) {
            dateFormats.add(new SimpleDateFormat(datePattern));
        }
    }
    
    DefaultDateTypeAdapter(Class<? extends Date> dateType, int style) {
        this.dateType = verifyDateType(dateType);
        dateFormats.add(DateFormat.getDateInstance(style, Locale.US));
        if (!Locale.getDefault().equals(Locale.US)) {
            dateFormats.add(DateFormat.getDateInstance(style));
        }
        if (JavaVersion.isJava9OrLater()) {
            dateFormats.add(PreJava9DateFormatProvider.getUSDateFormat(style));
        }
    }
    
    public DefaultDateTypeAdapter(int dateStyle, int timeStyle) {
        this(Date.class, dateStyle, timeStyle);
    }
    
    public DefaultDateTypeAdapter(Class<? extends Date> dateType, int dateStyle, int timeStyle) {
        this.dateType = verifyDateType(dateType);
        dateFormats.add(DateFormat.getDateTimeInstance(dateStyle, timeStyle, Locale.US));
        if (!Locale.getDefault().equals(Locale.US)) {
            dateFormats.add(DateFormat.getDateTimeInstance(dateStyle, timeStyle));
        }
        if (JavaVersion.isJava9OrLater()) {
            dateFormats.add(PreJava9DateFormatProvider.getUSDateTimeFormat(dateStyle, timeStyle));
        }
    }