You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2014/04/25 18:44:28 UTC

[3/3] git commit: ISIS-421: RO TCK tests and fixes

ISIS-421: RO TCK tests and fixes

mostly the JsonValueEncoder dealing with encoding/decoding to json of strings into primitives, wrappers, bigdecimal, biginteger and also (of course, everyone's favorite) dates.


Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/09437950
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/09437950
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/09437950

Branch: refs/heads/master
Commit: 09437950199579116d1afedeb95aa4438f58e8d8
Parents: 964e252
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Fri Apr 25 17:44:13 2014 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Fri Apr 25 17:44:13 2014 +0100

----------------------------------------------------------------------
 .../applib/JsonRepresentation.java              | 321 +++++++++++---
 .../ScalarValueRepresentation.java              |   3 +-
 .../JsonRepresentationTest_getBigDecimal.java   | 117 +++++
 .../JsonRepresentationTest_getBigInteger.java   |  84 ++--
 .../JsonRepresentationTest_getDouble.java       |  18 +-
 .../applib/JsonRepresentationTest_size.java     |  11 +-
 .../applib/client/RestfulClientTest_follow.java | 132 ------
 .../isis/viewer/restfulobjects/applib/map.json  |  25 +-
 .../domainobjects/DomainObjectReprRenderer.java |   3 +-
 .../domainobjects/JsonValueEncoder.java         | 346 ++++++++++-----
 .../ObjectPropertyReprRenderer.java             |   3 +-
 .../domainobjects/ScalarValueReprRenderer.java  |   5 +-
 ...onValueEncoderTest_appendValueAndFormat.java | 426 +++++++++++++++++++
 .../JsonValueEncoderTest_asAdapter.java         | 143 ++++---
 .../JsonValueEncoderTest_asObject.java          | 105 ++---
 .../server/resources/DomainResourceHelper.java  |   2 +-
 ...ontextTest_ensureCompatibleAcceptHeader.java |  33 +-
 .../server/ResourceContextTest_getArg.java      |  51 ++-
 ...WithJdkProperties_thenRepresentation_ok.java | 160 +++++++
 ...dkProperties_thenRepresentation_ok_TODO.java |  80 ----
 ...ithJodaProperties_thenRepresentation_ok.java | 122 ++++++
 ...daProperties_thenRepresentation_ok_TODO.java | 124 ------
 ...imitiveProperties_thenRepresentation_ok.java |   4 +-
 ...WrapperProperties_thenRepresentation_ok.java |  21 +-
 ...henArgsValid_thenMultiplePropertyUpdate.java |  37 +-
 ...Put_whenArgValid_thenPropertyUpdated_ok.java |  26 +-
 .../core/tck/dom/scalars/JdkValuedEntity.java   |  35 +-
 .../fixture/scalars/JdkValuedEntityFixture.java |  42 +-
 .../scalars/JodaValuedEntityFixture.java        |   4 +-
 29 files changed, 1720 insertions(+), 763 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/09437950/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/JsonRepresentation.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/JsonRepresentation.java b/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/JsonRepresentation.java
index 009bf42..ac7fe0e 100644
--- a/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/JsonRepresentation.java
+++ b/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/JsonRepresentation.java
@@ -24,6 +24,8 @@ import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.util.*;
 import java.util.Map.Entry;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 import com.google.common.base.Function;
 import com.google.common.base.Predicate;
 import com.google.common.collect.Iterables;
@@ -32,8 +34,9 @@ import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import org.codehaus.jackson.JsonNode;
 import org.codehaus.jackson.node.*;
-import org.joda.time.format.DateTimeFormat;
+import org.joda.time.LocalTime;
 import org.joda.time.format.DateTimeFormatter;
+import org.joda.time.format.ISODateTimeFormat;
 import org.apache.isis.viewer.restfulobjects.applib.util.JsonNodeUtils;
 import org.apache.isis.viewer.restfulobjects.applib.util.PathNode;
 import org.apache.isis.viewer.restfulobjects.applib.util.UrlEncodingUtils;
@@ -44,6 +47,9 @@ import org.apache.isis.viewer.restfulobjects.applib.util.UrlEncodingUtils;
  */
 public class JsonRepresentation {
 
+    private static final Pattern FORMAT_BIG_DECIMAL = Pattern.compile("big-decimal\\((\\d+),(\\d+)\\)");
+    private static final Pattern FORMAT_BIG_INTEGER = Pattern.compile("big-integer\\((\\d+)\\)");
+
     public interface HasLinkToSelf {
         public LinkRepresentation getSelf();
     }
@@ -307,7 +313,7 @@ public class JsonRepresentation {
     // getDate, asDate
     // ///////////////////////////////////////////////////////////////////////
 
-    public final static DateTimeFormatter yyyyMMdd = DateTimeFormat.forPattern("yyyy-MM-dd");
+    public final static DateTimeFormatter yyyyMMdd = ISODateTimeFormat.date().withZoneUTC();
 
     public java.util.Date getDate(final String path) {
         return getDate(path, getNode(path));
@@ -333,7 +339,7 @@ public class JsonRepresentation {
     // getDateTime, asDateTime
     // ///////////////////////////////////////////////////////////////////////
 
-    public final static DateTimeFormatter yyyyMMddTHHmmssZ = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ssZ");
+    public final static DateTimeFormatter yyyyMMddTHHmmssZ = ISODateTimeFormat.dateTimeNoMillis().withZoneUTC();
 
     public java.util.Date getDateTime(final String path) {
         return getDateTime(path, getNode(path));
@@ -359,7 +365,7 @@ public class JsonRepresentation {
     // getTime, asTime
     // ///////////////////////////////////////////////////////////////////////
 
-    public final static DateTimeFormatter _HHmmss = DateTimeFormat.forPattern("HH:mm:ss");
+    public final static DateTimeFormatter _HHmmss = ISODateTimeFormat.timeNoMillis().withZoneUTC();
 
     public java.util.Date getTime(final String path) {
         return getTime(path, getNode(path));
@@ -378,7 +384,8 @@ public class JsonRepresentation {
             throw new IllegalArgumentException(formatExMsg(path, "is not a time"));
         }
         final String textValue = node.getTextValue();
-        return new java.util.Date(_HHmmss.parseMillis(textValue));
+        final LocalTime localTime = _HHmmss.parseLocalTime(textValue + "Z");
+        return new java.util.Date(localTime.getMillisOfDay());
     }
 
     // ///////////////////////////////////////////////////////////////////////
@@ -423,9 +430,9 @@ public class JsonRepresentation {
     }
     
     // ///////////////////////////////////////////////////////////////////////
-    // getByte, asByte
+    // isByte, getByte, asByte
     // ///////////////////////////////////////////////////////////////////////
-    
+
     /**
      * Use {@link #isIntegralNumber(String)} to test if number (it is not possible to check if a byte, however).
      */
@@ -599,10 +606,13 @@ public class JsonRepresentation {
             return null;
         }
         checkValue(path, node, "a long");
-        if (!node.isLong()) {
-            throw new IllegalArgumentException(formatExMsg(path, "is not a long"));
+        if(node.isInt()) {
+            return Long.valueOf(node.getIntValue());
+        }
+        if(node.isLong()) {
+            return node.getLongValue();
         }
-        return node.getLongValue();
+        throw new IllegalArgumentException(formatExMsg(path, "is not a long"));
     }
 
     // ///////////////////////////////////////////////////////////////////////
@@ -610,7 +620,7 @@ public class JsonRepresentation {
     // ///////////////////////////////////////////////////////////////////////
 
     /**
-     * Use {@link #isNumber(String)} to test if number (it is not possible to check if a float, however).
+     * Use {@link #isDecimal(String)} to test if a decimal value
      */
     public Float getFloat(final String path) {
         final JsonNode node = getNode(path);
@@ -637,18 +647,34 @@ public class JsonRepresentation {
     
 
     // ///////////////////////////////////////////////////////////////////////
-    // isDouble, getDouble, asDouble
+    // isDecimal, isDouble, getDouble, asDouble
     // ///////////////////////////////////////////////////////////////////////
 
+    public boolean isDecimal(final String path) {
+        return isDecimal(getNode(path));
+    }
+
+    public boolean isDecimal() {
+        return isDecimal(asJsonNode());
+    }
+
+    /**
+     * @deprecated - use {@link #isDecimal(String)}
+     */
+    @Deprecated
     public boolean isDouble(final String path) {
-        return isDouble(getNode(path));
+        return isDecimal(path);
     }
 
+    /**
+     * @deprecated - use {@link #isDecimal()}
+     */
+    @Deprecated
     public boolean isDouble() {
-        return isDouble(asJsonNode());
+        return isDecimal();
     }
 
-    private boolean isDouble(final JsonNode node) {
+    private boolean isDecimal(final JsonNode node) {
         return !representsNull(node) && node.isValueNode() && node.isDouble();
     }
 
@@ -691,33 +717,90 @@ public class JsonRepresentation {
     }
 
     private boolean isBigInteger(final JsonNode node) {
-        return !representsNull(node) && node.isValueNode() && node.isBigInteger();
+        return !representsNull(node) && node.isValueNode() && (node.isBigInteger() || node.isLong() || node.isInt() || node.isTextual() && parseableAsBigInteger(node.getTextValue()));
+    }
+
+    private static boolean parseableAsBigInteger(String str) {
+        try {
+            new BigInteger(str);
+            return true;
+        } catch (Exception e) {
+            return false;
+        }
     }
 
     /**
      * Use {@link #isBigInteger(String)} to check first, if required.
      */
     public BigInteger getBigInteger(final String path) {
-        final JsonNode node = getNode(path);
-        return getBigInteger(path, node);
+        return getBigInteger(path, (String)null);
+    }
+
+    /**
+     * Use {@link #isBigInteger(String)} to check first, if required.
+     */
+    public BigInteger getBigInteger(final String path, final String formatRequested) {
+        final JsonNode node;
+        final String format;
+        if(formatRequested != null) {
+            node = getNode(path);
+            format = formatRequested;
+        } else {
+            final NodeAndFormat nodeAndFormat = getNodeAndFormat(path);
+            node = nodeAndFormat.node;
+            format = nodeAndFormat.format;
+        }
+        return getBigInteger(path, format, node);
     }
 
     /**
      * Use {@link #isBigInteger()} to check first, if required.
      */
     public BigInteger asBigInteger() {
-        return getBigInteger(null, asJsonNode());
+        return asBigInteger(null);
+    }
+
+    public BigInteger asBigInteger(final String format) {
+        return getBigInteger(null, format, asJsonNode());
     }
 
-    private BigInteger getBigInteger(final String path, final JsonNode node) {
+    private BigInteger getBigInteger(final String path, final String format, final JsonNode node) {
         if (representsNull(node)) {
             return null;
         }
-        checkValue(path, node, "a biginteger");
-        if (!node.isBigInteger()) {
-            throw new IllegalArgumentException(formatExMsg(path, "is not a biginteger"));
+        final String requiredType = "a biginteger";
+        if(!isBigInteger(node)) {
+            throw new IllegalArgumentException(formatExMsg(path, "is not " + requiredType));
+        }
+        checkValue(path, node, requiredType);
+        final BigInteger bigInteger = getBigInteger(path, node);
+        if(format != null) {
+            final Matcher matcher = FORMAT_BIG_INTEGER.matcher(format);
+            if(matcher.matches()) {
+                final int precision = Integer.parseInt(matcher.group(1));
+                final BigInteger maxAllowed = BigInteger.TEN.pow(precision);
+                if(bigInteger.compareTo(maxAllowed) > 0) {
+                    throw new IllegalArgumentException(String.format("Value '%s' larger than that allowed by format '%s'", bigInteger, format));
+                }
+            }
+        }
+        return bigInteger;
+    }
+
+    private BigInteger getBigInteger(String path, JsonNode node) {
+        if (node.isBigInteger()) {
+            return node.getBigIntegerValue();
+        }
+        if (node.isTextual()) {
+            return new BigInteger(node.getTextValue());
         }
-        return node.getBigIntegerValue();
+        if (node.isLong()) {
+            return BigInteger.valueOf(node.getLongValue());
+        }
+        if (node.isInt()) {
+            return BigInteger.valueOf(node.getIntValue());
+        }
+        throw new IllegalArgumentException(formatExMsg(path, "is not a biginteger, is not any other integral number, is not text parseable as a biginteger"));
     }
 
     // ///////////////////////////////////////////////////////////////////////
@@ -727,74 +810,95 @@ public class JsonRepresentation {
     public boolean isBigDecimal(final String path) {
         return isBigDecimal(getNode(path));
     }
-    public boolean isBigDecimalOrNumeric(final String path) {
-        return isBigDecimalOrNumeric(getNode(path));
-    }
 
     public boolean isBigDecimal() {
         return isBigDecimal(asJsonNode());
     }
-    public boolean isBigDecimalOrNumeric() {
-        return isBigDecimalOrNumeric(asJsonNode());
-    }
 
     private boolean isBigDecimal(final JsonNode node) {
-        return !representsNull(node) && node.isValueNode() && node.isBigDecimal();
+        return !representsNull(node) && node.isValueNode() && (node.isBigDecimal() || node.isDouble() || node.isLong() || node.isInt() || node.isBigInteger() || node.isTextual() && parseableAsBigDecimal(node.getTextValue()));
     }
-    private boolean isBigDecimalOrNumeric(final JsonNode node) {
-        return !representsNull(node) && node.isValueNode() && (node.isBigDecimal() || node.isDouble() || node.isLong() || node.isInt() || node.isBigInteger());
+
+    private static boolean parseableAsBigDecimal(String str) {
+        try {
+            new BigDecimal(str);
+            return true;
+        } catch (Exception e) {
+            return false;
+        }
     }
 
     /**
      * Use {@link #isBigDecimal(String)} to check first, if required.
      */
     public BigDecimal getBigDecimal(final String path) {
-        final JsonNode node = getNode(path);
-        return getBigDecimal(path, node);
+        return getBigDecimal(path, (String)null);
     }
+
     /**
      * Use {@link #isBigDecimal(String)} to check first, if required.
      */
-    public BigDecimal getBigDecimalFromNumeric(final String path) {
-        final JsonNode node = getNode(path);
-        return getBigDecimalFromNumeric(path, node);
+    public BigDecimal getBigDecimal(final String path, final String formatRequested) {
+        final JsonNode node;
+        final String format;
+        if(formatRequested != null) {
+            node = getNode(path);
+            format = formatRequested;
+        } else {
+            final NodeAndFormat nodeAndFormat = getNodeAndFormat(path);
+            node = nodeAndFormat.node;
+            format = nodeAndFormat.format;
+        }
+        return getBigDecimal(path, format, node);
     }
 
     /**
      * Use {@link #isBigDecimal()} to check first, if required.
      */
     public BigDecimal asBigDecimal() {
-        return getBigDecimal(null, asJsonNode());
+        return asBigDecimal(null);
     }
-    
+
     /**
-     * Use {@link #isBigDecimalOrNumeric()} to check first, if required.
+     * Use {@link #isBigDecimal()} to check first, if required.
      */
-    public BigDecimal asBigDecimalFromNumeric() {
-        return getBigDecimalFromNumeric(null, asJsonNode());
+    public BigDecimal asBigDecimal(String format) {
+        return getBigDecimal(null, format, asJsonNode());
     }
 
-    private BigDecimal getBigDecimal(final String path, final JsonNode node) {
+    private BigDecimal getBigDecimal(final String path, final String format, final JsonNode node) {
         if (representsNull(node)) {
             return null;
         }
-        checkValue(path, node, "a bigdecimal");
-        if (node.isBigDecimal()) {
-            return node.getDecimalValue();
+        final String requiredType = "a bigdecimal";
+        if(!isBigDecimal(node)) {
+            throw new IllegalArgumentException(formatExMsg(path, "is not " + requiredType));
+        }
+        checkValue(path, node, requiredType);
+        final BigDecimal bigDecimal = getBigDecimal(path, node);
+        if(format != null) {
+            final Matcher matcher = FORMAT_BIG_DECIMAL.matcher(format);
+            if(matcher.matches()) {
+                final int precision = Integer.parseInt(matcher.group(1));
+                final int scale = Integer.parseInt(matcher.group(2));
+                final BigDecimal maxAllowed = BigDecimal.TEN.pow(precision-scale);
+                if(bigDecimal.compareTo(maxAllowed) > 0) {
+                    throw new IllegalArgumentException(String.format("Value '%s' larger than that allowed by format '%s'", bigDecimal, format));
+                }
+                return bigDecimal.setScale(scale, BigDecimal.ROUND_HALF_EVEN);
+            }
         }
-        throw new IllegalArgumentException(formatExMsg(path, "is not a bigdecimal (or any other numeric)"));
+        return bigDecimal;
     }
 
-    private BigDecimal getBigDecimalFromNumeric(final String path, final JsonNode node) {
-        if (representsNull(node)) {
-            return null;
-        }
-        checkValue(path, node, "a bigdecimal");
+    private BigDecimal getBigDecimal(String path, JsonNode node) {
         if (node.isBigDecimal()) {
             return node.getDecimalValue();
         }
+        if (node.isTextual()) {
+            return new BigDecimal(node.getTextValue());
+        }
         if (node.isLong()) {
-            // there will be rounding errors, most likely
             return new BigDecimal(node.getLongValue());
         }
         if (node.isDouble()) {
@@ -802,16 +906,14 @@ public class JsonRepresentation {
             return new BigDecimal(node.getDoubleValue());
         }
         if (node.isBigInteger()) {
-            // there will be rounding errors, most likely
             return new BigDecimal(node.getBigIntegerValue());
         }
         if (node.isInt()) {
-            // there will be rounding errors, most likely
             return new BigDecimal(node.getIntValue());
         }
-        throw new IllegalArgumentException(formatExMsg(path, "is not a bigdecimal (or any other numeric)"));
+        throw new IllegalArgumentException(formatExMsg(path, "is not a bigdecimal, is not any other numeric, is not text parseable as a bigdecimal"));
     }
-    
+
 
     // ///////////////////////////////////////////////////////////////////////
     // getString, isString, asString
@@ -1242,7 +1344,7 @@ public class JsonRepresentation {
         }
         final Path path = Path.parse(key);
         final ObjectNode node = JsonNodeUtils.walkNodeUpTo(asObjectNode(), path.getHead());
-        node.put(path.getTail(), value != null? new POJONode(value): NullNode.getInstance() );
+        node.put(path.getTail(), value != null ? new POJONode(value) : NullNode.getInstance());
         return this;
     }
 
@@ -1285,7 +1387,23 @@ public class JsonRepresentation {
         return this;
     }
 
-    public JsonRepresentation mapPut(final String key, final long value) {
+    public JsonRepresentation mapPut(final String key, final byte value) {
+        return mapPut(key, (int)value);
+    }
+
+    public JsonRepresentation mapPut(final String key, final Byte value) {
+        return value != null ? mapPut(key, value.byteValue()) : mapPut(key, (Object) value);
+    }
+
+    public JsonRepresentation mapPut(final String key, final short value) {
+        return mapPut(key, (int)value);
+    }
+
+    public JsonRepresentation mapPut(final String key, final Short value) {
+        return value != null ? mapPut(key, value.shortValue()) : mapPut(key, (Object) value);
+    }
+
+    public JsonRepresentation mapPut(final String key, final int value) {
         if (!isMap()) {
             throw new IllegalStateException("does not represent map");
         }
@@ -1295,7 +1413,11 @@ public class JsonRepresentation {
         return this;
     }
 
-    public JsonRepresentation mapPut(final String key, final int value) {
+    public JsonRepresentation mapPut(final String key, final Integer value) {
+        return value != null ? mapPut(key, value.intValue()) : mapPut(key, (Object) value);
+    }
+
+    public JsonRepresentation mapPut(final String key, final long value) {
         if (!isMap()) {
             throw new IllegalStateException("does not represent map");
         }
@@ -1305,7 +1427,11 @@ public class JsonRepresentation {
         return this;
     }
 
-    public JsonRepresentation mapPut(final String key, final double value) {
+    public JsonRepresentation mapPut(final String key, final Long value) {
+        return value != null ? mapPut(key, value.longValue()) : mapPut(key, (Object) value);
+    }
+
+    public JsonRepresentation mapPut(final String key, final float value) {
         if (!isMap()) {
             throw new IllegalStateException("does not represent map");
         }
@@ -1315,7 +1441,11 @@ public class JsonRepresentation {
         return this;
     }
 
-    public JsonRepresentation mapPut(final String key, final float value) {
+    public JsonRepresentation mapPut(final String key, final Float value) {
+        return value != null ? mapPut(key, value.floatValue()) : mapPut(key, (Object) value);
+    }
+
+    public JsonRepresentation mapPut(final String key, final double value) {
         if (!isMap()) {
             throw new IllegalStateException("does not represent map");
         }
@@ -1325,6 +1455,10 @@ public class JsonRepresentation {
         return this;
     }
 
+    public JsonRepresentation mapPut(final String key, final Double value) {
+        return value != null ? mapPut(key, value.doubleValue()) : mapPut(key, (Object) value);
+    }
+
     public JsonRepresentation mapPut(final String key, final boolean value) {
         if (!isMap()) {
             throw new IllegalStateException("does not represent map");
@@ -1335,15 +1469,30 @@ public class JsonRepresentation {
         return this;
     }
 
+    public JsonRepresentation mapPut(final String key, final Boolean value) {
+        return value != null ? mapPut(key, value.booleanValue()) : mapPut(key, (Object) value);
+    }
+
+    public JsonRepresentation mapPut(final String key, final char value) {
+        return mapPut(key, ""+value);
+    }
+
+    public JsonRepresentation mapPut(final String key, final Character value) {
+        return value != null ? mapPut(key, value.charValue()) : mapPut(key, (Object) value);
+    }
+
     public JsonRepresentation mapPut(final String key, final BigInteger value) {
         if (!isMap()) {
             throw new IllegalStateException("does not represent map");
         }
         final Path path = Path.parse(key);
         final ObjectNode node = JsonNodeUtils.walkNodeUpTo(asObjectNode(), path.getHead());
-        node.put(path.getTail(), value != null? new BigIntegerNode(value): NullNode.getInstance() );
+        if (value != null) {
+            node.put(path.getTail(), value.toString());
+        } else {
+            node.put(path.getTail(), NullNode.getInstance());
+        }
         return this;
-
     }
 
     public JsonRepresentation mapPut(Iterable<Entry<String, JsonRepresentation>> entries) {
@@ -1364,7 +1513,11 @@ public class JsonRepresentation {
         }
         final Path path = Path.parse(key);
         final ObjectNode node = JsonNodeUtils.walkNodeUpTo(asObjectNode(), path.getHead());
-        node.put(path.getTail(), value != null? new DecimalNode(value): NullNode.getInstance() );
+        if (value != null) {
+            node.put(path.getTail(), value.toString());
+        } else {
+            node.put(path.getTail(), NullNode.getInstance());
+        }
         return this;
     }
 
@@ -1462,30 +1615,58 @@ public class JsonRepresentation {
     }
 
     private JsonNode getNode(final String path) {
+        return getNodeAndFormat(path).node;
+    }
+
+    private static class NodeAndFormat {
+        JsonNode node;
+        String format;
+        NodeAndFormat(JsonNode jsonNode, String format) {
+            node = jsonNode;
+            this.format = format;
+        }
+    }
+
+    /**
+     * Walks the path to the specified node, and also returns the value of 'format' in the parent node if present.
+     */
+    private NodeAndFormat getNodeAndFormat(final String path) {
         JsonNode jsonNode = this.jsonNode;
         final List<String> keys = PathNode.split(path);
+        String format = null;
         for (final String key : keys) {
             final PathNode pathNode = PathNode.parse(key);
             if (!pathNode.getKey().isEmpty()) {
+                // grab format (if present) before moving down the path
+                format = getFormatValueIfAnyFrom(jsonNode);
                 jsonNode = jsonNode.path(pathNode.getKey());
             } else {
                 // pathNode is criteria only; don't change jsonNode
             }
             if (jsonNode.isNull()) {
-                return jsonNode;
+                return new NodeAndFormat(jsonNode, format);
             }
             if (!pathNode.hasCriteria()) {
                 continue;
             }
             if (!jsonNode.isArray()) {
-                return NullNode.getInstance();
+                return new NodeAndFormat(NullNode.getInstance(), format);
             }
+            // grab format (if present) before moving down the path
+            format = getFormatValueIfAnyFrom(jsonNode);
             jsonNode = matching(jsonNode, pathNode);
             if (jsonNode.isNull()) {
-                return jsonNode;
+                return new NodeAndFormat(jsonNode, format);
             }
         }
-        return jsonNode;
+        return new NodeAndFormat(jsonNode, format);
+    }
+
+    private String getFormatValueIfAnyFrom(JsonNode jsonNode) {
+        String format;
+        final JsonNode formatNode = jsonNode.get("format");
+        format = formatNode != null && formatNode.isTextual()? formatNode.getTextValue(): null;
+        return format;
     }
 
     private JsonNode matching(final JsonNode jsonNode, final PathNode pathNode) {

http://git-wip-us.apache.org/repos/asf/isis/blob/09437950/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/domainobjects/ScalarValueRepresentation.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/domainobjects/ScalarValueRepresentation.java b/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/domainobjects/ScalarValueRepresentation.java
index fec5c0b..6f102a8 100644
--- a/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/domainobjects/ScalarValueRepresentation.java
+++ b/component/viewer/restfulobjects/applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/domainobjects/ScalarValueRepresentation.java
@@ -18,8 +18,8 @@
  */
 package org.apache.isis.viewer.restfulobjects.applib.domainobjects;
 
-import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
 import org.codehaus.jackson.JsonNode;
+import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
 
 public class ScalarValueRepresentation extends DomainRepresentation {
 
@@ -31,5 +31,4 @@ public class ScalarValueRepresentation extends DomainRepresentation {
         return getRepresentation("value");
     }
 
-
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/09437950/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/JsonRepresentationTest_getBigDecimal.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/JsonRepresentationTest_getBigDecimal.java b/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/JsonRepresentationTest_getBigDecimal.java
new file mode 100644
index 0000000..bcbe5bf
--- /dev/null
+++ b/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/JsonRepresentationTest_getBigDecimal.java
@@ -0,0 +1,117 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.viewer.restfulobjects.applib;
+
+import java.io.IOException;
+import java.math.BigDecimal;
+import org.codehaus.jackson.JsonParseException;
+import org.codehaus.jackson.map.JsonMappingException;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import static org.apache.isis.viewer.restfulobjects.applib.JsonFixture.readJson;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.junit.Assert.assertThat;
+
+public class JsonRepresentationTest_getBigDecimal {
+
+    @Rule
+    public ExpectedException expectedException = ExpectedException.none();
+
+    private JsonRepresentation jsonRepresentation;
+
+    @Before
+    public void setUp() throws Exception {
+        jsonRepresentation = new JsonRepresentation(readJson("map.json"));
+    }
+
+    @Test
+    public void happyCase() throws JsonParseException, JsonMappingException, IOException {
+        assertThat(jsonRepresentation.getBigDecimal("aBigDecimal"), is(new BigDecimal("12345678901234567890.1234")));
+    }
+
+    @Test
+    public void happyCaseForFormatJustFits() throws JsonParseException, JsonMappingException, IOException {
+        assertThat(jsonRepresentation.getBigDecimal("aBigDecimal", "big-decimal(24,4)"), is(new BigDecimal("12345678901234567890.1234")));
+    }
+
+    @Test
+    public void invalidFormat() throws JsonParseException, JsonMappingException, IOException {
+        expectedException.expect(IllegalArgumentException.class);
+        expectedException.expectMessage("Value '12345678901234567890.1234' larger than that allowed by format 'big-decimal(22,3)'");
+
+        assertThat(jsonRepresentation.getBigDecimal("aBigDecimal", "big-decimal(22,3)"), is(new BigDecimal("12345678901234567890")));
+    }
+
+    @Test
+    public void validFormattedFromPath() throws JsonParseException, JsonMappingException, IOException {
+        assertThat(jsonRepresentation.getBigDecimal("yetAnotherSubMap.aFormattedBigDecimal.value"), is(new BigDecimal("123.45")));
+    }
+
+    @Test
+    public void invalidFormattedFromPath() throws JsonParseException, JsonMappingException, IOException {
+        expectedException.expect(IllegalArgumentException.class);
+        expectedException.expectMessage("Value '123.45' larger than that allowed by format 'big-decimal(4,2)'");
+
+        jsonRepresentation.getBigDecimal("yetAnotherSubMap.anInvalidFormattedBigDecimal.value");
+    }
+
+    @Test
+    public void invalidFormattedFromPathButOverridden() throws JsonParseException, JsonMappingException, IOException {
+        assertThat(jsonRepresentation.getBigDecimal("yetAnotherSubMap.anInvalidFormattedBigDecimal.value", "big-decimal(5,2)"), is(new BigDecimal("123.45")));
+    }
+
+    @Test
+    public void forNonExistent() throws JsonParseException, JsonMappingException, IOException {
+        assertThat(jsonRepresentation.getBigDecimal("doesNotExist"), is(nullValue()));
+    }
+
+    @Test
+    public void forNonParseableString() throws JsonParseException, JsonMappingException, IOException {
+        expectedException.expect(IllegalArgumentException.class);
+        expectedException.expectMessage("'aString' is not a bigdecimal");
+
+        jsonRepresentation.getBigDecimal("aString");
+    }
+
+    @Test
+    public void forMap() throws JsonParseException, JsonMappingException, IOException {
+        expectedException.expect(IllegalArgumentException.class);
+        expectedException.expectMessage("'aSubMap' is not a bigdecimal");
+
+        jsonRepresentation.getBigDecimal("aSubMap");
+    }
+
+    @Test
+    public void forList() throws JsonParseException, JsonMappingException, IOException {
+        expectedException.expect(IllegalArgumentException.class);
+        expectedException.expectMessage("'aSubList' is not a bigdecimal");
+
+        jsonRepresentation.getBigDecimal("aSubList");
+    }
+
+    @Test
+    public void forMultipartKey() throws JsonParseException, JsonMappingException, IOException {
+        assertThat(jsonRepresentation.getBigDecimal("aSubMap.aBigDecimal"), is(new BigDecimal("12345678901234567890.1234")));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/09437950/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/JsonRepresentationTest_getBigInteger.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/JsonRepresentationTest_getBigInteger.java b/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/JsonRepresentationTest_getBigInteger.java
index e7af049..def1cfb 100644
--- a/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/JsonRepresentationTest_getBigInteger.java
+++ b/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/JsonRepresentationTest_getBigInteger.java
@@ -18,22 +18,25 @@
  */
 package org.apache.isis.viewer.restfulobjects.applib;
 
-import static org.apache.isis.viewer.restfulobjects.applib.JsonFixture.readJson;
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.CoreMatchers.nullValue;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.fail;
-
 import java.io.IOException;
 import java.math.BigInteger;
-
 import org.codehaus.jackson.JsonParseException;
 import org.codehaus.jackson.map.JsonMappingException;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import static org.apache.isis.viewer.restfulobjects.applib.JsonFixture.readJson;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.junit.Assert.assertThat;
 
 public class JsonRepresentationTest_getBigInteger {
 
+    @Rule
+    public ExpectedException expectedException = ExpectedException.none();
+
     private JsonRepresentation jsonRepresentation;
 
     @Before
@@ -43,7 +46,38 @@ public class JsonRepresentationTest_getBigInteger {
 
     @Test
     public void happyCase() throws JsonParseException, JsonMappingException, IOException {
-        assertThat(jsonRepresentation.getBigInteger("aBigInteger"), is(new BigInteger("12345678901234534132452342342789678234234")));
+        assertThat(jsonRepresentation.getBigInteger("aBigInteger"), is(new BigInteger("12345678901234567890")));
+    }
+
+    @Test
+    public void happyCaseForFormatJustFits() throws JsonParseException, JsonMappingException, IOException {
+        assertThat(jsonRepresentation.getBigInteger("aBigInteger", "big-integer(20)"), is(new BigInteger("12345678901234567890")));
+    }
+
+    @Test
+    public void invalidFormat() throws JsonParseException, JsonMappingException, IOException {
+        expectedException.expect(IllegalArgumentException.class);
+        expectedException.expectMessage("Value '12345678901234567890' larger than that allowed by format 'big-integer(19)'");
+
+        assertThat(jsonRepresentation.getBigInteger("aBigInteger", "big-integer(19)"), is(new BigInteger("12345678901234567890")));
+    }
+
+    @Test
+    public void validFormattedFromPath() throws JsonParseException, JsonMappingException, IOException {
+        assertThat(jsonRepresentation.getBigInteger("yetAnotherSubMap.aFormattedBigInteger.value"), is(new BigInteger("123")));
+    }
+
+    @Test
+    public void invalidFormattedFromPath() throws JsonParseException, JsonMappingException, IOException {
+        expectedException.expect(IllegalArgumentException.class);
+        expectedException.expectMessage("Value '123' larger than that allowed by format 'big-integer(2)'");
+
+        jsonRepresentation.getBigInteger("yetAnotherSubMap.anInvalidFormattedBigInteger.value");
+    }
+
+    @Test
+    public void invalidFormattedFromPathButOverridden() throws JsonParseException, JsonMappingException, IOException {
+        assertThat(jsonRepresentation.getBigInteger("yetAnotherSubMap.anInvalidFormattedBigInteger.value", "big-integer(3)"), is(new BigInteger("123")));
     }
 
     @Test
@@ -52,38 +86,32 @@ public class JsonRepresentationTest_getBigInteger {
     }
 
     @Test
-    public void forValueButNot() throws JsonParseException, JsonMappingException, IOException {
-        try {
-            jsonRepresentation.getBigInteger("aString");
-            fail();
-        } catch (final IllegalArgumentException e) {
-            assertThat(e.getMessage(), is("'aString' is not a biginteger"));
-        }
+    public void forNonParseableString() throws JsonParseException, JsonMappingException, IOException {
+        expectedException.expect(IllegalArgumentException.class);
+        expectedException.expectMessage("'aString' is not a biginteger");
+
+        jsonRepresentation.getBigInteger("aString");
     }
 
     @Test
     public void forMap() throws JsonParseException, JsonMappingException, IOException {
-        try {
-            jsonRepresentation.getBigInteger("aSubMap");
-            fail();
-        } catch (final IllegalArgumentException e) {
-            assertThat(e.getMessage(), is("'aSubMap' is not a biginteger"));
-        }
+        expectedException.expect(IllegalArgumentException.class);
+        expectedException.expectMessage("'aSubMap' is not a biginteger");
+
+        jsonRepresentation.getBigInteger("aSubMap");
     }
 
     @Test
     public void forList() throws JsonParseException, JsonMappingException, IOException {
-        try {
-            jsonRepresentation.getBigInteger("aSubList");
-            fail();
-        } catch (final IllegalArgumentException e) {
-            assertThat(e.getMessage(), is("'aSubList' is not a biginteger"));
-        }
+        expectedException.expect(IllegalArgumentException.class);
+        expectedException.expectMessage("'aSubList' is not a biginteger");
+
+        jsonRepresentation.getBigInteger("aSubList");
     }
 
     @Test
     public void forMultipartKey() throws JsonParseException, JsonMappingException, IOException {
-        assertThat(jsonRepresentation.getDouble("aSubMap.aDouble"), is(12345678901234534.4567));
+        assertThat(jsonRepresentation.getBigInteger("aSubMap.aBigInteger"), is(new BigInteger("12345678901234567890")));
     }
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/09437950/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/JsonRepresentationTest_getDouble.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/JsonRepresentationTest_getDouble.java b/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/JsonRepresentationTest_getDouble.java
index 4809a6d..43a745e 100644
--- a/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/JsonRepresentationTest_getDouble.java
+++ b/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/JsonRepresentationTest_getDouble.java
@@ -18,21 +18,25 @@
  */
 package org.apache.isis.viewer.restfulobjects.applib;
 
-import static org.apache.isis.viewer.restfulobjects.applib.JsonFixture.readJson;
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.CoreMatchers.nullValue;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.fail;
-
 import java.io.IOException;
-
 import org.codehaus.jackson.JsonParseException;
 import org.codehaus.jackson.map.JsonMappingException;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import static org.apache.isis.viewer.restfulobjects.applib.JsonFixture.readJson;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
 
 public class JsonRepresentationTest_getDouble {
 
+    @Rule
+    public ExpectedException expectedException = ExpectedException.none();
+
     private JsonRepresentation jsonRepresentation;
 
     @Before

http://git-wip-us.apache.org/repos/asf/isis/blob/09437950/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/JsonRepresentationTest_size.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/JsonRepresentationTest_size.java b/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/JsonRepresentationTest_size.java
index 967c6a9..3bcdb26 100644
--- a/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/JsonRepresentationTest_size.java
+++ b/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/JsonRepresentationTest_size.java
@@ -18,16 +18,15 @@
  */
 package org.apache.isis.viewer.restfulobjects.applib;
 
-import static org.apache.isis.viewer.restfulobjects.applib.JsonFixture.readJson;
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertThat;
-
 import java.io.IOException;
-
 import org.codehaus.jackson.JsonParseException;
 import org.codehaus.jackson.map.JsonMappingException;
 import org.junit.Test;
 
+import static org.apache.isis.viewer.restfulobjects.applib.JsonFixture.readJson;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
 public class JsonRepresentationTest_size {
 
     private JsonRepresentation jsonRepresentation;
@@ -41,7 +40,7 @@ public class JsonRepresentationTest_size {
     @Test
     public void size_forNonEmptyMap() throws JsonParseException, JsonMappingException, IOException {
         jsonRepresentation = new JsonRepresentation(readJson("map.json"));
-        assertThat(jsonRepresentation.size(), is(15));
+        assertThat(jsonRepresentation.size(), is(16));
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/isis/blob/09437950/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/client/RestfulClientTest_follow.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/client/RestfulClientTest_follow.java b/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/client/RestfulClientTest_follow.java
deleted file mode 100644
index 8e0926a..0000000
--- a/component/viewer/restfulobjects/applib/src/test/java/org/apache/isis/viewer/restfulobjects/applib/client/RestfulClientTest_follow.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package org.apache.isis.viewer.restfulobjects.applib.client;
-
-import java.net.URI;
-
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.MultivaluedMap;
-
-import org.hamcrest.Description;
-import org.hamcrest.Matcher;
-import org.hamcrest.TypeSafeMatcher;
-import org.jboss.resteasy.client.ClientExecutor;
-import org.jboss.resteasy.client.ClientRequest;
-import org.jboss.resteasy.client.core.BaseClientResponse;
-import org.jboss.resteasy.specimpl.MultivaluedMapImpl;
-import org.jboss.resteasy.specimpl.UriBuilderImpl;
-import org.jmock.Expectations;
-import org.jmock.auto.Mock;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Rule;
-import org.junit.Test;
-
-import org.apache.isis.core.unittestsupport.jmocking.JUnitRuleMockery2;
-import org.apache.isis.core.unittestsupport.jmocking.JUnitRuleMockery2.Mode;
-import org.apache.isis.viewer.restfulobjects.applib.JsonFixture;
-import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
-import org.apache.isis.viewer.restfulobjects.applib.LinkRepresentation;
-
-public class RestfulClientTest_follow {
-
-    @Rule
-    public JUnitRuleMockery2 context = JUnitRuleMockery2.createFor(Mode.INTERFACES_AND_CLASSES);
-
-    private final URI uri = URI.create("http://yadayada:8080");
-
-    @Mock
-    private ClientExecutor mockExecutor;
-
-    @Mock
-    private ClientRequest mockClientRequest;
-
-    @Mock
-    private BaseClientResponse<String> mockClientResponse;
-
-    private JsonRepresentation jsonRepresentation;
-
-    private RestfulClient client;
-
-    @Before
-    public void setUp() throws Exception {
-        jsonRepresentation = new JsonRepresentation(JsonFixture.readJson("map.json"));
-        client = new RestfulClient(uri, mockExecutor);
-    }
-
-    @Ignore("TODO")
-    @Test
-    public void follow_get() throws Exception {
-        final LinkRepresentation link = jsonRepresentation.getLink("aLink");
-
-        final String href = link.getHref();
-
-        // when
-        context.checking(new Expectations() {
-            {
-                one(mockExecutor).createRequest(with(any(UriBuilderImpl.class)));
-                will(returnValue(mockClientRequest));
-
-                one(mockExecutor).execute(mockClientRequest);
-                will(returnValue(mockClientResponse));
-
-                one(mockClientRequest).accept(MediaType.APPLICATION_JSON_TYPE);
-                atLeast(1).of(mockClientRequest).setHttpMethod("GET");
-
-                allowing(mockClientRequest).getHttpMethod();
-                will(returnValue("GET"));
-
-                oneOf(mockClientRequest).execute();
-                will(returnValue(mockClientResponse));
-
-                oneOf(mockClientResponse).setReturnType(String.class);
-                allowing(mockClientResponse);
-
-                final MultivaluedMap result = new MultivaluedMapImpl();
-                result.put("Content-Type", "application/json");
-                allowing(mockClientResponse).getMetadata();
-                will(returnValue(result));
-            }
-
-        });
-        final RestfulResponse<JsonRepresentation> response = client.follow(link);
-
-        // then
-    }
-
-    private static Matcher<ClientRequest> requestToHref(final String href) {
-        return new TypeSafeMatcher<ClientRequest>() {
-
-            @Override
-            public void describeTo(final Description description) {
-                description.appendText("request to href: " + href);
-            }
-
-            @Override
-            public boolean matchesSafely(final ClientRequest clientRequest) {
-                try {
-                    return clientRequest.getUri().equals(href);
-                } catch (final Exception e) {
-                    return false;
-                }
-            }
-        };
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/09437950/component/viewer/restfulobjects/applib/src/test/resources/org/apache/isis/viewer/restfulobjects/applib/map.json
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/applib/src/test/resources/org/apache/isis/viewer/restfulobjects/applib/map.json b/component/viewer/restfulobjects/applib/src/test/resources/org/apache/isis/viewer/restfulobjects/applib/map.json
index 2c9a7d1..d4f2d04 100644
--- a/component/viewer/restfulobjects/applib/src/test/resources/org/apache/isis/viewer/restfulobjects/applib/map.json
+++ b/component/viewer/restfulobjects/applib/src/test/resources/org/apache/isis/viewer/restfulobjects/applib/map.json
@@ -3,8 +3,8 @@
   "aNull": null,
   "aLong": 1234567890123,
   "aDouble": 12345678901234534.3242,
-  "aBigDecimal": 12345678901234534.3242,
-  "aBigInteger": 12345678901234534132452342342789678234234,
+  "aBigDecimal": "12345678901234567890.1234",
+  "aBigInteger": "12345678901234567890",
   "aBoolean": true,
   "aLink": {
     "href": "http://foo/bar",
@@ -20,13 +20,32 @@
     "aBoolean": true,
     "aLong": 1234567890456,
     "aDouble": 12345678901234534.4567,
-    "aBigInteger": 12345678901234534132452342342789678234234,
+    "aBigDecimal": "12345678901234567890.1234",
+    "aBigInteger": "12345678901234567890",
     "aLink": {
       "href": "http://foo/bar",
       "method": "GET",
       "rel": "someSubRel"
     }
   },
+  "yetAnotherSubMap": {
+    "aFormattedBigDecimal": {
+        "value":"123.45",
+        "format": "big-decimal(5,2)"
+    },
+    "anInvalidFormattedBigDecimal": {
+        "value":"123.45",
+        "format": "big-decimal(4,2)"
+    },
+    "aFormattedBigInteger": {
+        "value": "123",
+        "format": "big-integer(3)"
+    },
+    "anInvalidFormattedBigInteger": {
+        "value": "123",
+        "format": "big-integer(2)"
+    }
+  },
   "aSubList": [
     "a", "b", "c"
   ],

http://git-wip-us.apache.org/repos/asf/isis/blob/09437950/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/DomainObjectReprRenderer.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/DomainObjectReprRenderer.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/DomainObjectReprRenderer.java
index 49ef562..3bc4e51 100644
--- a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/DomainObjectReprRenderer.java
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/DomainObjectReprRenderer.java
@@ -351,7 +351,8 @@ public class DomainObjectReprRenderer extends ReprRendererAbstract<DomainObjectR
 
     public static Object valueOrRef(final RendererContext resourceContext, final ObjectAdapter objectAdapter, final ObjectSpecification objectSpec) {
         if(objectAdapter.isValue()) {
-            return JsonValueEncoder.asObject(objectAdapter);
+            String format = null; // TODO
+            return JsonValueEncoder.asObject(objectAdapter, format);
         }
         final TitleFacet titleFacet = objectSpec.getFacet(TitleFacet.class);
         final String title = titleFacet.title(objectAdapter, resourceContext.getLocalization());

http://git-wip-us.apache.org/repos/asf/isis/blob/09437950/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/JsonValueEncoder.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/JsonValueEncoder.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/JsonValueEncoder.java
index c3446b6..2afd9cd 100644
--- a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/JsonValueEncoder.java
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/JsonValueEncoder.java
@@ -49,6 +49,7 @@ import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
  */
 public final class JsonValueEncoder {
 
+
     private JsonValueEncoder(){}
 
     
@@ -79,13 +80,14 @@ public final class JsonValueEncoder {
         /**
          * The value, otherwise <tt>null</tt>.
          */
-        public abstract ObjectAdapter asAdapter(JsonRepresentation repr);
+        public abstract ObjectAdapter asAdapter(JsonRepresentation repr, String format);
         
-        public void appendValueAndFormat(ObjectAdapter objectAdapter, JsonRepresentation repr) {
-            append(repr, objectAdapter, format, xIsisFormat);
+        public void appendValueAndFormat(ObjectAdapter objectAdapter, String format, JsonRepresentation repr) {
+            repr.mapPut("value", unwrapAsObjectElseNullNode(objectAdapter));
+            appendFormats(repr, this.format, this.xIsisFormat);
         }
 
-        public Object asObject(ObjectAdapter objectAdapter) {
+        public Object asObject(ObjectAdapter objectAdapter, String format) {
             return objectAdapter.getObject();
         }
     }
@@ -102,27 +104,49 @@ public final class JsonValueEncoder {
     static {
         putConverter(new JsonValueConverter(null, "string", String.class){
             @Override
-            public ObjectAdapter asAdapter(JsonRepresentation repr) {
+            public ObjectAdapter asAdapter(JsonRepresentation repr, String format) {
                 if (repr.isString()) {
                     return adapterFor(repr.asString());
                 } 
                 return null;
             }
+            @Override
+            public void appendValueAndFormat(ObjectAdapter objectAdapter, String format, JsonRepresentation repr) {
+                final Object obj = unwrapAsObjectElseNullNode(objectAdapter);
+                if(obj instanceof String) {
+                    final String str = (String) obj;
+                    repr.mapPut("value", str);
+                } else {
+                    repr.mapPut("value", obj);
+                }
+                appendFormats(repr, this.format, xIsisFormat);
+            }
         });
 
         putConverter(new JsonValueConverter(null, "boolean", boolean.class, Boolean.class){
             @Override
-            public ObjectAdapter asAdapter(JsonRepresentation repr) {
+            public ObjectAdapter asAdapter(JsonRepresentation repr, String format) {
                 if (repr.isBoolean()) {
                     return adapterFor(repr.asBoolean());
                 } 
                 return null;
             }
+            @Override
+            public void appendValueAndFormat(ObjectAdapter objectAdapter, String format, JsonRepresentation repr) {
+                final Object obj = unwrapAsObjectElseNullNode(objectAdapter);
+                if(obj instanceof Boolean) {
+                    final Boolean b = (Boolean) obj;
+                    repr.mapPut("value", b);
+                } else {
+                    repr.mapPut("value", obj);
+                }
+                appendFormats(repr, this.format, xIsisFormat);
+            }
         });
         
-        putConverter(new JsonValueConverter(null, "byte", byte.class, Byte.class){
+        putConverter(new JsonValueConverter("int", "byte", byte.class, Byte.class){
             @Override
-            public ObjectAdapter asAdapter(JsonRepresentation repr) {
+            public ObjectAdapter asAdapter(JsonRepresentation repr, String format) {
                 if (repr.isNumber()) {
                     return adapterFor(repr.asNumber().byteValue());
                 }
@@ -137,11 +161,22 @@ public final class JsonValueEncoder {
                 }
                 return null;
             }
+            @Override
+            public void appendValueAndFormat(ObjectAdapter objectAdapter, String format, JsonRepresentation repr) {
+                final Object obj = unwrapAsObjectElseNullNode(objectAdapter);
+                if(obj instanceof Byte) {
+                    final Byte b = (Byte) obj;
+                    repr.mapPut("value", b);
+                } else {
+                    repr.mapPut("value", obj);
+                }
+                appendFormats(repr, this.format, xIsisFormat);
+            }
         });
         
-        putConverter(new JsonValueConverter(null, "short", short.class, Short.class){
+        putConverter(new JsonValueConverter("int", "short", short.class, Short.class){
             @Override
-            public ObjectAdapter asAdapter(JsonRepresentation repr) {
+            public ObjectAdapter asAdapter(JsonRepresentation repr, String format) {
                 if (repr.isNumber()) {
                     return adapterFor(repr.asNumber().shortValue());
                 }
@@ -156,11 +191,22 @@ public final class JsonValueEncoder {
                 }
                 return null;
             }
+            @Override
+            public void appendValueAndFormat(ObjectAdapter objectAdapter, String format, JsonRepresentation repr) {
+                final Object obj = unwrapAsObjectElseNullNode(objectAdapter);
+                if(obj instanceof Short) {
+                    final Short s = (Short) obj;
+                    repr.mapPut("value", s);
+                } else {
+                    repr.mapPut("value", obj);
+                }
+                appendFormats(repr, this.format, xIsisFormat);
+            }
         });
         
         putConverter(new JsonValueConverter("int", "int", int.class, Integer.class){
             @Override
-            public ObjectAdapter asAdapter(JsonRepresentation repr) {
+            public ObjectAdapter asAdapter(JsonRepresentation repr, String format) {
                 if (repr.isInt()) {
                     return adapterFor(repr.asInt());
                 }
@@ -175,11 +221,22 @@ public final class JsonValueEncoder {
                 }
                 return null;
             }
+            @Override
+            public void appendValueAndFormat(ObjectAdapter objectAdapter, String format, JsonRepresentation repr) {
+                final Object obj = unwrapAsObjectElseNullNode(objectAdapter);
+                if(obj instanceof Integer) {
+                    final Integer i = (Integer) obj;
+                    repr.mapPut("value", i);
+                } else {
+                    repr.mapPut("value", obj);
+                }
+                appendFormats(repr, this.format, xIsisFormat);
+            }
         });
         
         putConverter(new JsonValueConverter("int", "long", long.class, Long.class){
             @Override
-            public ObjectAdapter asAdapter(JsonRepresentation repr) {
+            public ObjectAdapter asAdapter(JsonRepresentation repr, String format) {
                 if (repr.isLong()) {
                     return adapterFor(repr.asLong());
                 }
@@ -194,11 +251,22 @@ public final class JsonValueEncoder {
                 }
                 return null;
             }
+            @Override
+            public void appendValueAndFormat(ObjectAdapter objectAdapter, String format, JsonRepresentation repr) {
+                final Object obj = unwrapAsObjectElseNullNode(objectAdapter);
+                if(obj instanceof Long) {
+                    final Long l = (Long) obj;
+                    repr.mapPut("value", l);
+                } else {
+                    repr.mapPut("value", obj);
+                }
+                appendFormats(repr, this.format, xIsisFormat);
+            }
         });
         
         putConverter(new JsonValueConverter("decimal", "float", float.class, Float.class){
             @Override
-            public ObjectAdapter asAdapter(JsonRepresentation repr) {
+            public ObjectAdapter asAdapter(JsonRepresentation repr, String format) {
                 if (repr.isDouble()) {
                     return adapterFor((float)(double)repr.asDouble());
                 }
@@ -216,11 +284,22 @@ public final class JsonValueEncoder {
                 }
                 return null;
             }
+            @Override
+            public void appendValueAndFormat(ObjectAdapter objectAdapter, String format, JsonRepresentation repr) {
+                final Object obj = unwrapAsObjectElseNullNode(objectAdapter);
+                if(obj instanceof Float) {
+                    final Float f = (Float) obj;
+                    repr.mapPut("value", f);
+                } else {
+                    repr.mapPut("value", obj);
+                }
+                appendFormats(repr, this.format, xIsisFormat);
+            }
         });
         
         putConverter(new JsonValueConverter("decimal", "double", double.class, Double.class){
             @Override
-            public ObjectAdapter asAdapter(JsonRepresentation repr) {
+            public ObjectAdapter asAdapter(JsonRepresentation repr, String format) {
                 if (repr.isDouble()) {
                     return adapterFor(repr.asDouble());
                 }
@@ -241,11 +320,22 @@ public final class JsonValueEncoder {
                 }
                 return null;
             }
+            @Override
+            public void appendValueAndFormat(ObjectAdapter objectAdapter, String format, JsonRepresentation repr) {
+                final Object obj = unwrapAsObjectElseNullNode(objectAdapter);
+                if(obj instanceof Double) {
+                    final Double d = (Double) obj;
+                    repr.mapPut("value", d);
+                } else {
+                    repr.mapPut("value", obj);
+                }
+                appendFormats(repr, this.format, xIsisFormat);
+            }
         });
         
         putConverter(new JsonValueConverter(null, "char", char.class, Character.class){
             @Override
-            public ObjectAdapter asAdapter(JsonRepresentation repr) {
+            public ObjectAdapter asAdapter(JsonRepresentation repr, String format) {
                 if (repr.isString()) {
                     final String str = repr.asString();
                     if(str != null && str.length()>0) {
@@ -262,13 +352,27 @@ public final class JsonValueEncoder {
                 }
                 return null;
             }
+            @Override
+            public void appendValueAndFormat(ObjectAdapter objectAdapter, String format, JsonRepresentation repr) {
+                final Object obj = unwrapAsObjectElseNullNode(objectAdapter);
+                if(obj instanceof Character) {
+                    final Character c = (Character) obj;
+                    repr.mapPut("value", c);
+                } else {
+                    repr.mapPut("value", obj);
+                }
+                appendFormats(repr, this.format, xIsisFormat);
+            }
         });
         
-        putConverter(new JsonValueConverter("int", "biginteger", BigInteger.class){
+        putConverter(new JsonValueConverter("big-integer", "javamathbiginteger", BigInteger.class){
             @Override
-            public ObjectAdapter asAdapter(JsonRepresentation repr) {
+            public ObjectAdapter asAdapter(JsonRepresentation repr, String format) {
+                if (repr.isString()) {
+                    return adapterFor(new BigInteger(repr.asString()));
+                }
                 if (repr.isBigInteger()) {
-                    return adapterFor(repr.asBigInteger());
+                    return adapterFor(repr.asBigInteger(format));
                 }
                 if (repr.isLong()) {
                     return adapterFor(BigInteger.valueOf(repr.asLong()));
@@ -281,14 +385,27 @@ public final class JsonValueEncoder {
                 }
                 return null;
             }
+            @Override
+            public void appendValueAndFormat(ObjectAdapter objectAdapter, String format, JsonRepresentation repr) {
+                final Object obj = unwrapAsObjectElseNullNode(objectAdapter);
+                if(obj instanceof BigInteger) {
+                    final BigInteger bi = (BigInteger) obj;
+                    repr.mapPut("value", bi);
+                } else {
+                    repr.mapPut("value", obj);
+                }
+                appendFormats(repr, format != null? format: this.format, xIsisFormat);
+            }
         });
         
-        putConverter(new JsonValueConverter("decimal", "bigdecimal", BigDecimal.class){
+        putConverter(new JsonValueConverter("big-decimal", "javamathbigdecimal", BigDecimal.class){
             @Override
-            public ObjectAdapter asAdapter(JsonRepresentation repr) {
-                // TODO: if inferring a BigDecimal, need to get the scale from somewhere...
+            public ObjectAdapter asAdapter(JsonRepresentation repr, String format) {
+                if (repr.isString()) {
+                    return adapterFor(new BigDecimal(repr.asString()));
+                }
                 if (repr.isBigDecimal()) {
-                    return adapterFor(repr.asBigDecimal());
+                    return adapterFor(repr.asBigDecimal(format));
                 }
                 if (repr.isBigInteger()) {
                     return adapterFor(new BigDecimal(repr.asBigInteger()));
@@ -305,21 +422,30 @@ public final class JsonValueEncoder {
                 return null;
             }
             @Override
-            public void appendValueAndFormat(ObjectAdapter objectAdapter, JsonRepresentation repr) {
-                super.appendValueAndFormat(objectAdapter, repr);
+            public void appendValueAndFormat(ObjectAdapter objectAdapter, String format, JsonRepresentation repr) {
+                final Object obj = unwrapAsObjectElseNullNode(objectAdapter);
+                if(obj instanceof BigDecimal) {
+                    final BigDecimal bd = (BigDecimal) obj;
+                    repr.mapPut("value", bd);
+                } else {
+                    repr.mapPut("value", obj);
+                }
+                appendFormats(repr, format != null? format: this.format, xIsisFormat);
             }
         });
 
         putConverter(new JsonValueConverter("date", "jodalocaldate", LocalDate.class){
 
+            // these formatters do NOT use withZoneUTC()
             final List<DateTimeFormatter> formatters = Arrays.asList(
-                    JsonRepresentation.yyyyMMdd, 
+                    ISODateTimeFormat.date(),
+                    ISODateTimeFormat.basicDate(),
                     DateTimeFormat.forPattern("yyyyMMdd"),
-                    ISODateTimeFormat.basicDate()
+                    JsonRepresentation.yyyyMMdd
                     );
 
             @Override
-            public ObjectAdapter asAdapter(JsonRepresentation repr) {
+            public ObjectAdapter asAdapter(JsonRepresentation repr, String format) {
                 if (repr.isString()) {
                     final String dateStr = repr.asString();
                     for (DateTimeFormatter formatter : formatters) {
@@ -335,29 +461,31 @@ public final class JsonValueEncoder {
             }
 
             @Override
-            public void appendValueAndFormat(ObjectAdapter objectAdapter, JsonRepresentation repr) {
-                final Object obj = unwrap(objectAdapter);
+            public void appendValueAndFormat(ObjectAdapter objectAdapter, String format, JsonRepresentation repr) {
+                final Object obj = unwrapAsObjectElseNullNode(objectAdapter);
                 if(obj instanceof LocalDate) {
                     final LocalDate date = (LocalDate) obj;
                     final String dateStr = formatters.get(0).print(date.toDateTimeAtStartOfDay());
-                    append(repr, dateStr, format, xIsisFormat);
+                    repr.mapPut("value", dateStr);
                 } else {
-                    append(repr, obj, format, xIsisFormat);
+                    repr.mapPut("value", obj);
                 }
+                appendFormats(repr, this.format, xIsisFormat);
             }
         });
 
         putConverter(new JsonValueConverter("date-time", "jodalocaldatetime", LocalDateTime.class){
-            
+
             final List<DateTimeFormatter> formatters = Arrays.asList(
-                    JsonRepresentation.yyyyMMddTHHmmssZ, 
-                    DateTimeFormat.forPattern("yyyyMMdd'T'HHmmssZ"), 
-                    ISODateTimeFormat.basicDateTimeNoMillis(),
-                    ISODateTimeFormat.basicDateTime()
+                    ISODateTimeFormat.dateTimeNoMillis().withZoneUTC(),
+                    ISODateTimeFormat.dateTime().withZoneUTC(),
+                    ISODateTimeFormat.basicDateTimeNoMillis().withZoneUTC(),
+                    ISODateTimeFormat.basicDateTime().withZoneUTC(),
+                    JsonRepresentation.yyyyMMddTHHmmssZ.withZoneUTC()
                     );
             
             @Override
-            public ObjectAdapter asAdapter(JsonRepresentation repr) {
+            public ObjectAdapter asAdapter(JsonRepresentation repr, String format) {
                 if (repr.isString()) {
                     final String dateStr = repr.asString();
                     for (DateTimeFormatter formatter : formatters) {
@@ -373,29 +501,31 @@ public final class JsonValueEncoder {
             }
 
             @Override
-            public void appendValueAndFormat(ObjectAdapter objectAdapter, JsonRepresentation repr) {
-                final Object obj = unwrap(objectAdapter); 
+            public void appendValueAndFormat(ObjectAdapter objectAdapter, String format, JsonRepresentation repr) {
+                final Object obj = unwrapAsObjectElseNullNode(objectAdapter);
                 if(obj instanceof LocalDateTime) {
                     final LocalDateTime date = (LocalDateTime) obj;
                     final String dateStr = formatters.get(0).print(date.toDateTime());
-                    append(repr, dateStr, format, xIsisFormat);
+                    repr.mapPut("value", dateStr);
                 } else {
-                    append(repr, obj, format, xIsisFormat);
+                    repr.mapPut("value", obj);
                 }
+                appendFormats(repr, this.format, xIsisFormat);
             }
         });
 
         putConverter(new JsonValueConverter("date-time", "jodadatetime", DateTime.class){
             
             final List<DateTimeFormatter> formatters = Arrays.asList(
-                    JsonRepresentation.yyyyMMddTHHmmssZ, 
-                    DateTimeFormat.forPattern("yyyyMMdd'T'HHmmssZ"), 
-                    ISODateTimeFormat.basicDateTimeNoMillis(),
-                    ISODateTimeFormat.basicDateTime()
+                    ISODateTimeFormat.dateTimeNoMillis().withZoneUTC(),
+                    ISODateTimeFormat.dateTime().withZoneUTC(),
+                    ISODateTimeFormat.basicDateTimeNoMillis().withZoneUTC(),
+                    ISODateTimeFormat.basicDateTime().withZoneUTC(),
+                    JsonRepresentation.yyyyMMddTHHmmssZ.withZoneUTC()
                     );
             
             @Override
-            public ObjectAdapter asAdapter(JsonRepresentation repr) {
+            public ObjectAdapter asAdapter(JsonRepresentation repr, String format) {
                 if (repr.isString()) {
                     final String dateStr = repr.asString();
                     for (DateTimeFormatter formatter : formatters) {
@@ -411,28 +541,30 @@ public final class JsonValueEncoder {
             }
 
             @Override
-            public void appendValueAndFormat(ObjectAdapter objectAdapter, JsonRepresentation repr) {
-                final Object obj = unwrap(objectAdapter); 
+            public void appendValueAndFormat(ObjectAdapter objectAdapter, String format, JsonRepresentation repr) {
+                final Object obj = unwrapAsObjectElseNullNode(objectAdapter);
                 if(obj instanceof DateTime) {
                     final DateTime date = (DateTime) obj;
                     final String dateStr = formatters.get(0).print(date.toDateTime());
-                    append(repr, dateStr, format, xIsisFormat);
+                    repr.mapPut("value", dateStr);
                 } else {
-                    append(repr, obj, format, xIsisFormat);
+                    repr.mapPut("value", obj);
                 }
+                appendFormats(repr, this.format, xIsisFormat);
             }
         });
 
-        putConverter(new JsonValueConverter("date", "javautildate", java.util.Date.class){
+        putConverter(new JsonValueConverter("date-time", "javautildate", java.util.Date.class){
             
             final List<DateTimeFormatter> formatters = Arrays.asList(
-                    JsonRepresentation.yyyyMMddTHHmmssZ, 
-                    DateTimeFormat.forPattern("yyyyMMdd'T'HHmmssZ"), 
-                    ISODateTimeFormat.basicDateTimeNoMillis(),
-                    ISODateTimeFormat.basicDateTime()
+                    ISODateTimeFormat.dateTimeNoMillis().withZoneUTC(),
+                    ISODateTimeFormat.dateTime().withZoneUTC(),
+                    ISODateTimeFormat.basicDateTimeNoMillis().withZoneUTC(),
+                    ISODateTimeFormat.basicDateTime().withZoneUTC(),
+                    JsonRepresentation.yyyyMMddTHHmmssZ.withZoneUTC()
                     );
             @Override
-            public ObjectAdapter asAdapter(JsonRepresentation repr) {
+            public ObjectAdapter asAdapter(JsonRepresentation repr, String format) {
                 if (repr.isString()) {
                     final String dateStr = repr.asString();
                     for (DateTimeFormatter formatter : formatters) {
@@ -449,27 +581,29 @@ public final class JsonValueEncoder {
             }
 
             @Override
-            public void appendValueAndFormat(ObjectAdapter objectAdapter, JsonRepresentation repr) {
-                final Object obj = unwrap(objectAdapter); 
+            public void appendValueAndFormat(ObjectAdapter objectAdapter, String format, JsonRepresentation repr) {
+                final Object obj = unwrapAsObjectElseNullNode(objectAdapter);
                 if(obj instanceof java.util.Date) {
                     final java.util.Date date = (java.util.Date) obj;
-                    final String dateStr = formatters.get(0).print(new DateTime(date));
-                    append(repr, dateStr, format, xIsisFormat);
+                    final DateTimeFormatter dateTimeFormatter = formatters.get(0);
+                    final String dateStr = dateTimeFormatter.print(new DateTime(date));
+                    repr.mapPut("value", dateStr);
                 } else {
-                    append(repr, obj, format, xIsisFormat);
+                    repr.mapPut("value", obj);
                 }
+                appendFormats(repr, this.format, xIsisFormat);
             }
         });
 
         putConverter(new JsonValueConverter("date", "javasqldate", java.sql.Date.class){
             
             final List<DateTimeFormatter> formatters = Arrays.asList(
-                            JsonRepresentation.yyyyMMdd, 
-                            DateTimeFormat.forPattern("yyyyMMdd"),
-                            ISODateTimeFormat.basicDate()
-                            );
+                    ISODateTimeFormat.date().withZoneUTC(),
+                    ISODateTimeFormat.basicDate().withZoneUTC(),
+                    JsonRepresentation.yyyyMMdd.withZoneUTC()
+                    );
             @Override
-            public ObjectAdapter asAdapter(JsonRepresentation repr) {
+            public ObjectAdapter asAdapter(JsonRepresentation repr, String format) {
                 if (repr.isString()) {
                     final String dateStr = repr.asString();
                     for (DateTimeFormatter formatter : formatters) {
@@ -486,26 +620,29 @@ public final class JsonValueEncoder {
             }
 
             @Override
-            public void appendValueAndFormat(ObjectAdapter objectAdapter, JsonRepresentation repr) {
-                final Object obj = unwrap(objectAdapter); 
+            public void appendValueAndFormat(ObjectAdapter objectAdapter, String format, JsonRepresentation repr) {
+                final Object obj = unwrapAsObjectElseNullNode(objectAdapter);
                 if(obj instanceof java.sql.Date) {
                     final java.sql.Date date = (java.sql.Date) obj;
                     final String dateStr = formatters.get(0).print(new DateTime(date));
-                    append(repr, dateStr, format, xIsisFormat);
+                    repr.mapPut("value", dateStr);
                 } else {
-                    append(repr, obj, format, xIsisFormat);
+                    repr.mapPut("value", obj);
                 }
+                appendFormats(repr, this.format, xIsisFormat);
             }
         });
 
-        putConverter(new JsonValueConverter("date", "javasqltime", java.sql.Time.class){
+        putConverter(new JsonValueConverter("time", "javasqltime", java.sql.Time.class){
             
             final List<DateTimeFormatter> formatters = Arrays.asList(
-                        JsonRepresentation._HHmmss, 
-                        DateTimeFormat.forPattern("HHmmss"), 
-                        ISODateTimeFormat.basicTime());
+                        ISODateTimeFormat.hourMinuteSecond().withZoneUTC(),
+                        ISODateTimeFormat.basicTimeNoMillis().withZoneUTC(),
+                        ISODateTimeFormat.basicTime().withZoneUTC(),
+                        JsonRepresentation._HHmmss.withZoneUTC()
+            );
             @Override
-            public ObjectAdapter asAdapter(JsonRepresentation repr) {
+            public ObjectAdapter asAdapter(JsonRepresentation repr, String format) {
                 if (repr.isString()) {
                     final String dateStr = repr.asString();
                     for (DateTimeFormatter formatter : formatters) {
@@ -522,22 +659,23 @@ public final class JsonValueEncoder {
             }
 
             @Override
-            public void appendValueAndFormat(ObjectAdapter objectAdapter, JsonRepresentation repr) {
-                final Object obj = unwrap(objectAdapter); 
+            public void appendValueAndFormat(ObjectAdapter objectAdapter, String format, JsonRepresentation repr) {
+                final Object obj = unwrapAsObjectElseNullNode(objectAdapter);
                 if(obj instanceof java.sql.Time) {
                     final java.sql.Time date = (java.sql.Time) obj;
                     final String dateStr = formatters.get(0).print(new DateTime(date));
-                    append(repr, dateStr, format, xIsisFormat);
+                    repr.mapPut("value", dateStr);
                 } else {
-                    append(repr, obj, format, xIsisFormat);
+                    repr.mapPut("value", obj);
                 }
+                appendFormats(repr, this.format, xIsisFormat);
             }
         });
 
         putConverter(new JsonValueConverter("utc-millisec", "javasqltimestamp", java.sql.Timestamp.class){
             
             @Override
-            public ObjectAdapter asAdapter(JsonRepresentation repr) {
+            public ObjectAdapter asAdapter(JsonRepresentation repr, String format) {
                 if (repr.isLong()) {
                     final Long millis = repr.asLong();
                     final java.sql.Timestamp parsedTimestamp = new java.sql.Timestamp(millis);
@@ -557,25 +695,29 @@ public final class JsonValueEncoder {
             }
 
             @Override
-            public void appendValueAndFormat(ObjectAdapter objectAdapter, JsonRepresentation repr) {
-                final Object obj = unwrap(objectAdapter); 
+            public void appendValueAndFormat(ObjectAdapter objectAdapter, String format, JsonRepresentation repr) {
+                final Object obj = unwrapAsObjectElseNullNode(objectAdapter);
                 if(obj instanceof java.sql.Timestamp) {
                     final java.sql.Timestamp date = (java.sql.Timestamp) obj;
                     final long millisStr = date.getTime();
-                    append(repr, millisStr, format, xIsisFormat);
+                    repr.mapPut("value", millisStr);
                 } else {
-                    append(repr, obj, format, xIsisFormat);
+                    repr.mapPut("value", obj);
                 }
+                appendFormats(repr, this.format, xIsisFormat);
             }
         });
     }
 
 
 
-    public static ObjectAdapter asAdapter(final ObjectSpecification objectSpec, final JsonRepresentation argValueRepr) {
+    public static ObjectAdapter asAdapter(final ObjectSpecification objectSpec, final JsonRepresentation argValueRepr, final String format) {
         if(argValueRepr == null) {
             return null;
         }
+        if (objectSpec == null) {
+            throw new IllegalArgumentException("ObjectSpecification is required");
+        }
         if (!argValueRepr.isValue()) {
             throw new IllegalArgumentException("Representation must be of a value");
         }
@@ -597,7 +739,7 @@ public final class JsonValueEncoder {
             throw new IllegalArgumentException("Unable to parse value");
         }
 
-        final ObjectAdapter asAdapter = jvc.asAdapter(argValueRepr);
+        final ObjectAdapter asAdapter = jvc.asAdapter(argValueRepr, format);
         if(asAdapter != null) {
             return asAdapter;
         }
@@ -615,22 +757,23 @@ public final class JsonValueEncoder {
         throw new IllegalArgumentException("Could not parse value '" + argValueRepr.asString() + "' as a " + objectSpec.getFullIdentifier());
     }
 
-    public static void appendValueAndFormat(ObjectSpecification objectSpec, ObjectAdapter objectAdapter, JsonRepresentation repr) {
+    public static void appendValueAndFormat(ObjectSpecification objectSpec, ObjectAdapter objectAdapter, JsonRepresentation repr, String format) {
 
         final JsonValueConverter jvc = converterBySpec.get(objectSpec.getSpecId());
         if(jvc != null) {
-            jvc.appendValueAndFormat(objectAdapter, repr);
+            jvc.appendValueAndFormat(objectAdapter, format, repr);
         } else {
             final EncodableFacet encodableFacet = objectSpec.getFacet(EncodableFacet.class);
             if (encodableFacet == null) {
                 throw new IllegalArgumentException("objectSpec expected to have EncodableFacet");
             }
             Object value = objectAdapter != null? encodableFacet.toEncodedString(objectAdapter): NullNode.getInstance();
-            append(repr, value, "string", "string");
+            repr.mapPut("value", value);
+            appendFormats(repr, "string", "string");
         }
     }
     
-    public static Object asObject(final ObjectAdapter objectAdapter) {
+    public static Object asObject(final ObjectAdapter objectAdapter, final String format) {
         if (objectAdapter == null) {
             throw new IllegalArgumentException("objectAdapter cannot be null");
         }
@@ -638,7 +781,7 @@ public final class JsonValueEncoder {
 
         final JsonValueConverter jvc = converterBySpec.get(objectSpec.getSpecId());
         if(jvc != null) {
-            return jvc.asObject(objectAdapter);
+            return jvc.asObject(objectAdapter, format);
         } 
         
         // else
@@ -649,10 +792,8 @@ public final class JsonValueEncoder {
         return encodableFacet.toEncodedString(objectAdapter);
     }
 
-    
 
-    private static void append(JsonRepresentation repr, Object value, String format, String xIsisFormat) {
-        repr.mapPut("value", value);
+    private static void appendFormats(JsonRepresentation repr, String format, String xIsisFormat) {
         if(format != null) {
             repr.mapPut("format", format);
         }
@@ -661,11 +802,7 @@ public final class JsonValueEncoder {
         }
     }
 
-    private static void append(JsonRepresentation repr, ObjectAdapter value, String format, String xIsisFormat) {
-        append(repr, unwrap(value), format, xIsisFormat);
-    }
-    
-    private static Object unwrap(ObjectAdapter objectAdapter) {
+    private static Object unwrapAsObjectElseNullNode(ObjectAdapter objectAdapter) {
         return objectAdapter != null? objectAdapter.getObject(): NullNode.getInstance();
     }
 
@@ -674,9 +811,16 @@ public final class JsonValueEncoder {
     private static ObjectAdapter adapterFor(Object value) {
         return getAdapterManager().adapterFor(value);
     }
-    
+
+    private static AdapterManager testAdapterManager;
+
+    // for testing purposes only
+    static void testSetAdapterManager(AdapterManager adapterManager) {
+        JsonValueEncoder.testAdapterManager = adapterManager;
+    }
+
     public static AdapterManager getAdapterManager() {
-        return IsisContext.getPersistenceSession().getAdapterManager();
+        return testAdapterManager != null? testAdapterManager:  IsisContext.getPersistenceSession().getAdapterManager();
     }
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/09437950/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectPropertyReprRenderer.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectPropertyReprRenderer.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectPropertyReprRenderer.java
index c131991..37a123b 100644
--- a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectPropertyReprRenderer.java
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectPropertyReprRenderer.java
@@ -70,7 +70,8 @@ public class ObjectPropertyReprRenderer extends AbstractObjectMemberReprRenderer
         
         final ValueFacet valueFacet = spec.getFacet(ValueFacet.class);
         if (valueFacet != null) {
-            JsonValueEncoder.appendValueAndFormat(spec, valueAdapter, representation);
+            String format = null; // TODO
+            JsonValueEncoder.appendValueAndFormat(spec, valueAdapter, representation, format);
             return;
         }