You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@asterixdb.apache.org by dl...@apache.org on 2021/09/23 17:48:44 UTC

[asterixdb] branch master updated: [NO ISSUE][API] Introduce Lossless-ADM-JSON encoding

This is an automated email from the ASF dual-hosted git repository.

dlych pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/asterixdb.git


The following commit(s) were added to refs/heads/master by this push:
     new 26fb94c  [NO ISSUE][API] Introduce Lossless-ADM-JSON encoding
26fb94c is described below

commit 26fb94c404692db7d93001de02e507ba9db00b65
Author: Dmitry Lychagin <dm...@couchbase.com>
AuthorDate: Tue Sep 21 14:43:09 2021 -0700

    [NO ISSUE][API] Introduce Lossless-ADM-JSON encoding
    
    - user model changes: no
    - storage format changes: no
    - interface changes: yes
    
    Details:
    - Lossless-ADM-JSON encodes ADM value into a nearly
      lossless JSON representation. It can then be parsed
      back into the original ADM value with the following differences:
    - Multsets are encoded as JSON arrays, so they are parsed back as arrays
    - All lists and records are parsed back as fully open ADM instances
    - The format is documented in LosslessADMJSONPrinterFactoryProvider
    - Add SessionConfig.OutputFormat.LOSSLESS_ADM_JSON constant
      to indicate this format
    - Add testcases
    - Minor refactoring in some utility classes
    
    Change-Id: I94902632cce647a7b40ebfd7e5e9c514d43e388f
    Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/13324
    Reviewed-by: Ian Maxon <im...@uci.edu>
    Tested-by: Jenkins <je...@fulliautomatix.ics.uci.edu>
    Integration-Tests: Jenkins <je...@fulliautomatix.ics.uci.edu>
---
 .../apache/asterix/translator/SessionConfig.java   |   3 +-
 .../apache/asterix/api/common/APIFramework.java    |   2 +
 .../api/http/server/QueryResultApiServlet.java     |   8 +-
 .../http/server/QueryServiceRequestParameters.java |  10 +-
 .../api/http/server/QueryServiceServlet.java       |   3 +-
 .../asterix/app/result/ResultPrinterTest.java      |   3 +-
 .../apache/asterix/test/common/TestExecutor.java   |   3 +-
 .../scan/alltypes_01/alltypes_01.4.query.sqlpp     |  33 +--
 .../scan/alltypes_01-cleanjson/alltypes_01.1.json  |   3 +-
 .../scan/alltypes_01-cleanjson/alltypes_01.2.json  |   1 +
 .../alltypes_01-losslessadmjson/alltypes_01.1.json |   1 +
 .../alltypes_01-losslessadmjson/alltypes_01.2.json |   1 +
 .../alltypes_01-losslessjson/alltypes_01.1.json    |   3 +-
 .../alltypes_01-losslessjson/alltypes_01.2.json    |   1 +
 .../results/scan/alltypes_01/alltypes_01.2.adm     |   1 +
 .../scan/alltypes_01/alltypes_01.4.ast             |  20 ++
 .../test/resources/runtimets/testsuite_sqlpp.xml   |  12 +-
 .../resources/runtimets/testsuite_sqlpp_parser.xml |   5 -
 .../external/parser/AbstractDataParser.java        |  48 +++-
 .../external/parser/AbstractJsonDataParser.java    |  18 +-
 .../external/parser/AbstractNestedDataParser.java  |   6 +-
 .../external/parser/LosslessADMJSONDataParser.java | 302 +++++++++++++++++++++
 .../parser/test/LosslessADMJSONDataParserTest.java | 287 ++++++++++++++++++++
 .../data/nontagged/printers/PrintTools.java        |   9 +-
 .../printers/adm/AUUIDPrinterFactory.java          |  13 +-
 .../printers/csv/AUUIDPrinterFactory.java          |  13 +-
 .../printers/json/clean/AUUIDPrinterFactory.java   |  13 +-
 .../json/lossless/AUUIDPrinterFactory.java         |  13 +-
 .../ABinaryPrinterFactory.java}                    |  23 +-
 .../ABooleanPrinterFactory.java}                   |  20 +-
 .../ACirclePrinterFactory.java}                    |  30 +-
 .../ADatePrinterFactory.java}                      |  21 +-
 .../ADateTimePrinterFactory.java}                  |  21 +-
 .../ADayTimeDurationPrinterFactory.java}           |  19 +-
 .../ADoublePrinterFactory.java}                    |  24 +-
 .../ADurationPrinterFactory.java}                  |  27 +-
 .../AFloatPrinterFactory.java}                     |  24 +-
 .../AInt16PrinterFactory.java}                     |  21 +-
 .../AInt32PrinterFactory.java}                     |  21 +-
 .../AInt64PrinterFactory.java}                     |  17 +-
 .../AInt8PrinterFactory.java}                      |  21 +-
 .../json/losslessadm/ALinePrinterFactory.java      |  56 ++++
 .../AMissingPrinterFactory.java}                   |  28 +-
 .../ANullPrinterFactory.java}                      |  18 +-
 .../json/losslessadm/AObjectPrinterFactory.java    | 161 +++++++++++
 .../losslessadm/AOptionalFieldPrinterFactory.java  |  73 +++++
 .../losslessadm/AOrderedlistPrinterFactory.java    |  68 +++++
 .../APoint3DPrinterFactory.java}                   |  30 +-
 .../APointPrinterFactory.java}                     |  27 +-
 .../json/losslessadm/APolygonPrinterFactory.java   |  57 ++++
 .../json/losslessadm/ARecordPrinterFactory.java    |  68 +++++
 .../json/losslessadm/ARectanglePrinterFactory.java |  56 ++++
 .../AStringPrinterFactory.java}                    |  36 ++-
 .../json/losslessadm/ATaggedValuePrinter.java      |  67 +++++
 .../ATimePrinterFactory.java}                      |  22 +-
 .../AUUIDPrinterFactory.java                       |  14 +-
 .../json/losslessadm/AUnionPrinterFactory.java     |  74 +++++
 .../losslessadm/AUnorderedlistPrinterFactory.java  |  72 +++++
 .../AYearMonthDurationPrinterFactory.java}         |  21 +-
 .../serde/ADoubleSerializerDeserializer.java       |   5 +-
 .../serde/AFloatSerializerDeserializer.java        |   4 +
 .../serde/AObjectSerializerDeserializer.java       |  14 +
 .../apache/asterix/formats/base/IDataFormat.java   |   2 +
 .../LosslessADMJSONPrinterFactoryProvider.java     | 226 +++++++++++++++
 .../org/apache/asterix/om/base/AOrderedList.java   |   2 +-
 .../java/org/apache/asterix/om/base/AUUID.java     |  35 ++-
 .../org/apache/asterix/om/base/AUnorderedList.java |   2 +-
 .../org/apache/asterix/om/base/InMemUtils.java     |   4 +-
 .../om/base/temporal/ADurationParserFactory.java   |  69 ++---
 .../om/pointables/printer/AListPrinter.java        |   6 +-
 .../om/pointables/printer/ARecordPrinter.java      |  13 +-
 .../printer/json/losslessadm/APrintVisitor.java    |  67 +++++
 .../runtime/evaluators/common/NumberUtils.java     |  23 +-
 .../runtime/formats/NonTaggedDataFormat.java       |   6 +
 .../testframework/context/TestCaseContext.java     |   3 +
 .../src/main/resources/Catalog.xsd                 |   1 +
 .../hyracks/data/std/primitive/FloatPointable.java |   2 +-
 .../java/org/apache/hyracks/util/StringUtil.java   |  17 ++
 .../apache/hyracks/util/bytes/Base64Parser.java    | 186 ++++++++-----
 .../org/apache/hyracks/util/bytes/HexParser.java   |  10 +-
 .../org/apache/hyracks/util/bytes/HexPrinter.java  |  12 +-
 81 files changed, 2321 insertions(+), 460 deletions(-)

diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SessionConfig.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SessionConfig.java
index 8077172..de31277 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SessionConfig.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SessionConfig.java
@@ -48,7 +48,8 @@ public class SessionConfig implements Serializable {
         ADM,
         CSV,
         CLEAN_JSON,
-        LOSSLESS_JSON
+        LOSSLESS_JSON,
+        LOSSLESS_ADM_JSON
     }
 
     /**
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/APIFramework.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/APIFramework.java
index e46177a..9292296 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/APIFramework.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/APIFramework.java
@@ -344,6 +344,8 @@ public class APIFramework {
         switch (outputFormat) {
             case LOSSLESS_JSON:
                 return format.getLosslessJSONPrinterFactoryProvider();
+            case LOSSLESS_ADM_JSON:
+                return format.getLosslessADMJSONPrinterFactoryProvider();
             case CSV:
                 return format.getCSVPrinterFactoryProvider();
             case ADM:
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryResultApiServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryResultApiServlet.java
index f705b89..981cdc9 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryResultApiServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryResultApiServlet.java
@@ -94,7 +94,8 @@ public class QueryResultApiServlet extends AbstractQueryApiServlet {
             SessionOutput sessionOutput = initResponse(request, response, metadata.getFormat());
             ResponsePrinter printer = new ResponsePrinter(sessionOutput);
             if (metadata.getFormat() == SessionConfig.OutputFormat.CLEAN_JSON
-                    || metadata.getFormat() == SessionConfig.OutputFormat.LOSSLESS_JSON) {
+                    || metadata.getFormat() == SessionConfig.OutputFormat.LOSSLESS_JSON
+                    || metadata.getFormat() == SessionConfig.OutputFormat.LOSSLESS_ADM_JSON) {
                 final Stats stats = new Stats();
                 printer.begin();
                 printer.addResultPrinter(new ResultsPrinter(appCtx, resultReader, null, stats, sessionOutput));
@@ -150,7 +151,8 @@ public class QueryResultApiServlet extends AbstractQueryApiServlet {
         // If it's JSON or ADM, check for the "wrapper-array" flag. Default is
         // "true" for JSON and "false" for ADM. (Not applicable for CSV.)
         boolean wrapperArray =
-                format == SessionConfig.OutputFormat.CLEAN_JSON || format == SessionConfig.OutputFormat.LOSSLESS_JSON;
+                format == SessionConfig.OutputFormat.CLEAN_JSON || format == SessionConfig.OutputFormat.LOSSLESS_JSON
+                        || format == SessionConfig.OutputFormat.LOSSLESS_ADM_JSON;
         String wrapperParam = request.getParameter("wrapper-array");
         if (wrapperParam != null) {
             wrapperArray = Boolean.valueOf(wrapperParam);
@@ -167,6 +169,8 @@ public class QueryResultApiServlet extends AbstractQueryApiServlet {
             case ADM:
                 HttpUtil.setContentType(response, "application/x-adm", request);
                 break;
+            case LOSSLESS_ADM_JSON:
+                // No need to reflect in output type; fall through
             case CLEAN_JSON:
                 // No need to reflect "clean-ness" in output type; fall through
             case LOSSLESS_JSON:
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceRequestParameters.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceRequestParameters.java
index 3211f62..2b0b314 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceRequestParameters.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceRequestParameters.java
@@ -90,7 +90,8 @@ public class QueryServiceRequestParameters {
 
     private enum Attribute {
         HEADER("header"),
-        LOSSLESS("lossless");
+        LOSSLESS("lossless"),
+        LOSSLESS_ADM("lossless-adm");
 
         private final String str;
 
@@ -586,8 +587,11 @@ public class QueryServiceRequestParameters {
         if (mimeSplits.length > 0) {
             String format = mimeSplits[0].toLowerCase().trim();
             if (format.equals(HttpUtil.ContentType.APPLICATION_JSON)) {
-                return Pair.of(hasValue(mimeSplits, Attribute.LOSSLESS.str(), booleanValues)
-                        ? OutputFormat.LOSSLESS_JSON : OutputFormat.CLEAN_JSON, Boolean.FALSE);
+                return Pair
+                        .of(hasValue(mimeSplits, Attribute.LOSSLESS.str(), booleanValues) ? OutputFormat.LOSSLESS_JSON
+                                : hasValue(mimeSplits, Attribute.LOSSLESS_ADM.str(), booleanValues)
+                                        ? OutputFormat.LOSSLESS_ADM_JSON : OutputFormat.CLEAN_JSON,
+                                Boolean.FALSE);
             } else if (format.equals(HttpUtil.ContentType.TEXT_CSV)) {
                 return Pair.of(OutputFormat.CSV,
                         hasValue(mimeSplits, Attribute.HEADER.str(), csvHeaderValues) ? Boolean.TRUE : Boolean.FALSE);
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java
index abe9716..cb26574 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java
@@ -492,7 +492,8 @@ public class QueryServiceServlet extends AbstractQueryApiServlet {
         sessionConfig.set(SessionConfig.OOB_HYRACKS_JOB, param.isJob());
         sessionConfig.set(SessionConfig.FORMAT_INDENT_JSON, param.isPretty());
         sessionConfig.set(SessionConfig.FORMAT_QUOTE_RECORD,
-                format != SessionConfig.OutputFormat.CLEAN_JSON && format != SessionConfig.OutputFormat.LOSSLESS_JSON);
+                format != SessionConfig.OutputFormat.CLEAN_JSON && format != SessionConfig.OutputFormat.LOSSLESS_JSON
+                        && format != SessionConfig.OutputFormat.LOSSLESS_ADM_JSON);
         sessionConfig.set(SessionConfig.FORMAT_CSV_HEADER, param.isCSVWithHeader());
     }
 
diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/app/result/ResultPrinterTest.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/app/result/ResultPrinterTest.java
index e3e4069..5974e28 100644
--- a/asterixdb/asterix-app/src/test/java/org/apache/asterix/app/result/ResultPrinterTest.java
+++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/app/result/ResultPrinterTest.java
@@ -97,7 +97,8 @@ public class ResultPrinterTest {
         sessionConfig.set(SessionConfig.FORMAT_WRAPPER_ARRAY, true);
         sessionConfig.set(SessionConfig.FORMAT_INDENT_JSON, true);
         sessionConfig.set(SessionConfig.FORMAT_QUOTE_RECORD,
-                format != SessionConfig.OutputFormat.CLEAN_JSON && format != SessionConfig.OutputFormat.LOSSLESS_JSON);
+                format != SessionConfig.OutputFormat.CLEAN_JSON && format != SessionConfig.OutputFormat.LOSSLESS_JSON
+                        && format != SessionConfig.OutputFormat.LOSSLESS_ADM_JSON);
         return new SessionOutput(sessionConfig, resultWriter, resultPrefix, resultPostfix, appendHandle, appendStatus);
     }
 
diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestExecutor.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestExecutor.java
index 9945570..3a8ef36 100644
--- a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestExecutor.java
+++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/TestExecutor.java
@@ -841,7 +841,8 @@ public class TestExecutor {
     }
 
     private static boolean setFormatInAccept(OutputFormat fmt) {
-        return fmt == OutputFormat.LOSSLESS_JSON || fmt == OutputFormat.CSV_HEADER;
+        return fmt == OutputFormat.LOSSLESS_JSON || fmt == OutputFormat.LOSSLESS_ADM_JSON
+                || fmt == OutputFormat.CSV_HEADER;
     }
 
     public void setAvailableCharsets(Charset... charsets) {
diff --git a/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/bytes/HexPrinter.java b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/scan/alltypes_01/alltypes_01.4.query.sqlpp
similarity index 51%
copy from hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/bytes/HexPrinter.java
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/scan/alltypes_01/alltypes_01.4.query.sqlpp
index d340526..21f37f1 100644
--- a/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/bytes/HexPrinter.java
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/scan/alltypes_01/alltypes_01.4.query.sqlpp
@@ -17,32 +17,9 @@
  * under the License.
  */
 
-package org.apache.hyracks.util.bytes;
+use test;
 
-import java.io.IOException;
-
-public class HexPrinter {
-    public enum Case {
-        LOWER_CASE('a'),
-        UPPER_CASE('A');
-
-        private final char a;
-
-        Case(char a) {
-            this.a = a;
-        }
-    }
-
-    public static byte hex(int i, Case c) {
-        return (byte) (i < 10 ? i + '0' : i + (c.a - 10));
-    }
-
-    public static Appendable printHexString(byte[] bytes, int start, int length, Appendable appendable)
-            throws IOException {
-        for (int i = 0; i < length; ++i) {
-            appendable.append((char) hex((bytes[start + i] >>> 4) & 0x0f, Case.UPPER_CASE));
-            appendable.append((char) hex((bytes[start + i] & 0x0f), Case.UPPER_CASE));
-        }
-        return appendable;
-    }
-}
+{
+  "t1_array_of_unknown": [ null, missing ],
+  "t2_multiset_of_unknown": {{ null, missing }}
+};
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/scan/alltypes_01-cleanjson/alltypes_01.1.json b/asterixdb/asterix-app/src/test/resources/runtimets/results/scan/alltypes_01-cleanjson/alltypes_01.1.json
index dd319a4..707f9a2 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/scan/alltypes_01-cleanjson/alltypes_01.1.json
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/scan/alltypes_01-cleanjson/alltypes_01.1.json
@@ -1,2 +1 @@
-[ { "id": 10, "string": "Nancy", "float": 32.5, "double": -2013.5938237483274, "boolean": true, "int8": 125, "int16": 32765, "int32": 294967295, "int64": 1700000000000000000, "unorderedList": [ "reading", "writing" ], "orderedList": [ "Brad", "Scott" ], "record": { "number": 8389, "street": "Hill St.", "city": "Mountain View" }, "date": "-2011-01-27", "time": "12:20:30.000Z", "datetime": "-1951-12-27T12:20:30.000Z", "duration": "P10Y11M12DT10H50M30S", "point": [41.0, 44.0], "point3d": [4 [...]
- ]
+{ "id": 10, "string": "Nancy", "float": 32.5, "double": -2013.5938237483274, "boolean": true, "int8": 125, "int16": 32765, "int32": 294967295, "int64": 1700000000000000000, "unorderedList": [ "reading", "writing" ], "orderedList": [ "Brad", "Scott" ], "record": { "number": 8389, "street": "Hill St.", "city": "Mountain View" }, "date": "-2011-01-27", "time": "12:20:30.000", "datetime": "-1951-12-27T12:20:30.000", "duration": "P10Y11M12DT10H50M30S", "point": [ 41.0, 44.0 ], "point3d": [ 44 [...]
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/scan/alltypes_01-cleanjson/alltypes_01.2.json b/asterixdb/asterix-app/src/test/resources/runtimets/results/scan/alltypes_01-cleanjson/alltypes_01.2.json
new file mode 100644
index 0000000..aeb5ce5
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/scan/alltypes_01-cleanjson/alltypes_01.2.json
@@ -0,0 +1 @@
+{ "t1_array_of_unknown": [ null, null ], "t2_multiset_of_unknown": [ null, null ] }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/scan/alltypes_01-losslessadmjson/alltypes_01.1.json b/asterixdb/asterix-app/src/test/resources/runtimets/results/scan/alltypes_01-losslessadmjson/alltypes_01.1.json
new file mode 100644
index 0000000..62acb55
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/scan/alltypes_01-losslessadmjson/alltypes_01.1.json
@@ -0,0 +1 @@
+{ "id": 10, "string": ":Nancy", "float": "0B:1107427328", "double": "0C:-4566801342117107042", "boolean": true, "int8": "01:125", "int16": "02:32765", "int32": "03:294967295", "int64": 1700000000000000000, "unorderedList": [ ":reading", ":writing" ], "orderedList": [ ":Brad", ":Scott" ], "record": { "number": 8389, "street": ":Hill St.", "city": ":Mountain View" }, "date": "11:-1454004", "time": "12:44430000", "datetime": "10:-123703587570000", "duration": "13:131:1075830000", "point": " [...]
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/scan/alltypes_01-losslessadmjson/alltypes_01.2.json b/asterixdb/asterix-app/src/test/resources/runtimets/results/scan/alltypes_01-losslessadmjson/alltypes_01.2.json
new file mode 100644
index 0000000..3510c7d
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/scan/alltypes_01-losslessadmjson/alltypes_01.2.json
@@ -0,0 +1 @@
+{ "t1_array_of_unknown": [ null, "0E" ], "t2_multiset_of_unknown": [ null, "0E" ] }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/scan/alltypes_01-losslessjson/alltypes_01.1.json b/asterixdb/asterix-app/src/test/resources/runtimets/results/scan/alltypes_01-losslessjson/alltypes_01.1.json
index 2e99438..a4148c3 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/scan/alltypes_01-losslessjson/alltypes_01.1.json
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/scan/alltypes_01-losslessjson/alltypes_01.1.json
@@ -1,2 +1 @@
-[ { "id": { "int64": 10 }, "string": "Nancy", "float": 32.5, "double": -2013.5938237483274, "boolean": true, "int8": { "int8": 125 }, "int16": { "int16": 32765 }, "int32": { "int32": 294967295 }, "int64": { "int64": 1700000000000000000 }, "unorderedList": { "unorderedlist": [ "reading", "writing" ] }, "orderedList": { "orderedlist": [ "Brad", "Scott" ] }, "record": { "number": { "int64": 8389 }, "street": "Hill St.", "city": "Mountain View" }, "date": { "date": "-2011-01-27" }, "time": { [...]
- ]
+{ "id": { "int64": 10 }, "string": "Nancy", "float": 32.5, "double": -2013.5938237483274, "boolean": true, "int8": { "int8": 125 }, "int16": { "int16": 32765 }, "int32": { "int32": 294967295 }, "int64": { "int64": 1700000000000000000 }, "unorderedList": { "unorderedlist": [ "reading", "writing" ] }, "orderedList": { "orderedlist": [ "Brad", "Scott" ] }, "record": { "number": { "int64": 8389 }, "street": "Hill St.", "city": "Mountain View" }, "date": { "date": "-2011-01-27" }, "time": { " [...]
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/scan/alltypes_01-losslessjson/alltypes_01.2.json b/asterixdb/asterix-app/src/test/resources/runtimets/results/scan/alltypes_01-losslessjson/alltypes_01.2.json
new file mode 100644
index 0000000..f0a1c92
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/scan/alltypes_01-losslessjson/alltypes_01.2.json
@@ -0,0 +1 @@
+{ "t1_array_of_unknown": { "orderedlist": [ null, null ] }, "t2_multiset_of_unknown": { "unorderedlist": [ null, null ] } }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/scan/alltypes_01/alltypes_01.2.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/scan/alltypes_01/alltypes_01.2.adm
new file mode 100644
index 0000000..abea200
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/scan/alltypes_01/alltypes_01.2.adm
@@ -0,0 +1 @@
+{ "t1_array_of_unknown": [ null, null ], "t2_multiset_of_unknown": {{ null, null }} }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/scan/alltypes_01/alltypes_01.4.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/scan/alltypes_01/alltypes_01.4.ast
new file mode 100644
index 0000000..9cbf7f3
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/scan/alltypes_01/alltypes_01.4.ast
@@ -0,0 +1,20 @@
+DataverseUse test
+Query:
+RecordConstructor [
+  (
+    LiteralExpr [STRING] [t1_array_of_unknown]
+    :
+    OrderedListConstructor [
+      LiteralExpr [NULL]
+      LiteralExpr [MISSING]
+    ]
+  )
+  (
+    LiteralExpr [STRING] [t2_multiset_of_unknown]
+    :
+    UnorderedListConstructor [
+      LiteralExpr [NULL]
+      LiteralExpr [MISSING]
+    ]
+  )
+]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
index 9590b1e..43f7697 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp.xml
@@ -9719,7 +9719,17 @@
     </test-case>
     <test-case FilePath="scan">
       <compilation-unit name="alltypes_01">
-        <output-dir compare="Text">alltypes_01</output-dir>
+        <output-dir compare="Clean-JSON">alltypes_01-cleanjson</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="scan">
+      <compilation-unit name="alltypes_01">
+        <output-dir compare="Lossless-JSON">alltypes_01-losslessjson</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="scan">
+      <compilation-unit name="alltypes_01">
+        <output-dir compare="Lossless-ADM-JSON">alltypes_01-losslessadmjson</output-dir>
       </compilation-unit>
     </test-case>
     <test-case FilePath="scan">
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp_parser.xml b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp_parser.xml
index 6d85178..a96c57e 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp_parser.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite_sqlpp_parser.xml
@@ -4415,11 +4415,6 @@
       </compilation-unit>
     </test-case>
     <test-case FilePath="scan">
-      <compilation-unit name="alltypes_01">
-        <output-dir compare="AST">alltypes_01</output-dir>
-      </compilation-unit>
-    </test-case>
-    <test-case FilePath="scan">
       <compilation-unit name="alltypes_02">
         <output-dir compare="AST">alltypes_02</output-dir>
       </compilation-unit>
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/AbstractDataParser.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/AbstractDataParser.java
index cec4b2e..6c84403 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/AbstractDataParser.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/AbstractDataParser.java
@@ -41,6 +41,7 @@ import org.apache.asterix.om.base.AInt64;
 import org.apache.asterix.om.base.AInt8;
 import org.apache.asterix.om.base.AInterval;
 import org.apache.asterix.om.base.ALine;
+import org.apache.asterix.om.base.AMissing;
 import org.apache.asterix.om.base.AMutableBinary;
 import org.apache.asterix.om.base.AMutableCircle;
 import org.apache.asterix.om.base.AMutableDate;
@@ -58,6 +59,7 @@ import org.apache.asterix.om.base.AMutableInterval;
 import org.apache.asterix.om.base.AMutableLine;
 import org.apache.asterix.om.base.AMutablePoint;
 import org.apache.asterix.om.base.AMutablePoint3D;
+import org.apache.asterix.om.base.AMutablePolygon;
 import org.apache.asterix.om.base.AMutableRectangle;
 import org.apache.asterix.om.base.AMutableString;
 import org.apache.asterix.om.base.AMutableTime;
@@ -66,6 +68,7 @@ import org.apache.asterix.om.base.AMutableYearMonthDuration;
 import org.apache.asterix.om.base.ANull;
 import org.apache.asterix.om.base.APoint;
 import org.apache.asterix.om.base.APoint3D;
+import org.apache.asterix.om.base.APolygon;
 import org.apache.asterix.om.base.ARectangle;
 import org.apache.asterix.om.base.AString;
 import org.apache.asterix.om.base.ATime;
@@ -78,8 +81,10 @@ import org.apache.asterix.om.base.temporal.ADurationParserFactory.ADurationParse
 import org.apache.asterix.om.base.temporal.ATimeParserFactory;
 import org.apache.asterix.om.types.ATypeTag;
 import org.apache.asterix.om.types.BuiltinType;
+import org.apache.asterix.runtime.evaluators.common.NumberUtils;
 import org.apache.hyracks.api.dataflow.value.ISerializerDeserializer;
 import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.apache.hyracks.util.StringUtil;
 import org.apache.hyracks.util.bytes.Base64Parser;
 import org.apache.hyracks.util.bytes.HexParser;
 import org.apache.hyracks.util.string.UTF8StringReader;
@@ -114,6 +119,7 @@ public abstract class AbstractDataParser implements IDataParser {
     protected AMutableRectangle aRectangle = new AMutableRectangle(null, null);
     protected AMutablePoint aPoint2 = new AMutablePoint(0, 0);
     protected AMutableLine aLine = new AMutableLine(null, null);
+    protected AMutablePolygon aPolygon = new AMutablePolygon(null);
     protected AMutableDate aDate = new AMutableDate(0);
     protected AMutableInterval aInterval = new AMutableInterval(0L, 0L, (byte) 0);
 
@@ -146,6 +152,9 @@ public abstract class AbstractDataParser implements IDataParser {
     protected ISerializerDeserializer<ABoolean> booleanSerde =
             SerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.ABOOLEAN);
     @SuppressWarnings("unchecked")
+    protected ISerializerDeserializer<AMissing> missingSerde =
+            SerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.AMISSING);
+    @SuppressWarnings("unchecked")
     protected ISerializerDeserializer<ANull> nullSerde =
             SerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.ANULL);
 
@@ -201,6 +210,9 @@ public abstract class AbstractDataParser implements IDataParser {
     protected final static ISerializerDeserializer<ALine> lineSerde =
             SerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.ALINE);
     @SuppressWarnings("unchecked")
+    protected final static ISerializerDeserializer<APolygon> polygonSerde =
+            SerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.APOLYGON);
+    @SuppressWarnings("unchecked")
     protected static final ISerializerDeserializer<AInterval> intervalSerde =
             SerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(BuiltinType.AINTERVAL);
 
@@ -235,13 +247,13 @@ public abstract class AbstractDataParser implements IDataParser {
 
     protected void parseDateTimeDuration(char[] buffer, int begin, int len, DataOutput out)
             throws HyracksDataException {
-        ADurationParserFactory.parseDuration(buffer, begin, len, aDayTimeDuration, ADurationParseOption.All);
+        ADurationParserFactory.parseDuration(buffer, begin, len, aDayTimeDuration, ADurationParseOption.DAY_TIME);
         dayTimeDurationSerde.serialize(aDayTimeDuration, out);
     }
 
     protected void parseYearMonthDuration(char[] buffer, int begin, int len, DataOutput out)
             throws HyracksDataException {
-        ADurationParserFactory.parseDuration(buffer, begin, len, aYearMonthDuration, ADurationParseOption.All);
+        ADurationParserFactory.parseDuration(buffer, begin, len, aYearMonthDuration, ADurationParseOption.YEAR_MONTH);
         yearMonthDurationSerde.serialize(aYearMonthDuration, out);
     }
 
@@ -342,6 +354,11 @@ public abstract class AbstractDataParser implements IDataParser {
         binarySerde.serialize(aBinary, out);
     }
 
+    protected void parseUUID(char[] buffer, int start, int length, DataOutput out) throws HyracksDataException {
+        aUUID.parseUUIDString(buffer, start, length);
+        uuidSerde.serialize(aUUID, out);
+    }
+
     protected long parseDatePart(String interval, int startOffset, int endOffset) throws HyracksDataException {
 
         while (interval.charAt(endOffset) == '"' || interval.charAt(endOffset) == ' ') {
@@ -368,16 +385,33 @@ public abstract class AbstractDataParser implements IDataParser {
         return ATimeParserFactory.parseTimePart(interval, startOffset, endOffset - startOffset + 1);
     }
 
-    protected double parseDouble(char[] buffer, int begin, int len) {
+    protected double parseDouble(char[] buffer, int begin, int len) throws ParseException {
         // TODO: parse double directly from char[]
         String str = new String(buffer, begin, len);
-        return Double.valueOf(str);
+        try {
+            return Double.parseDouble(str);
+        } catch (NumberFormatException e) {
+            throw new ParseException(ErrorCode.PARSER_ADM_DATA_PARSER_WRONG_INSTANCE, e, str,
+                    BuiltinType.ADOUBLE.getTypeName());
+        }
     }
 
-    protected float parseFloat(char[] buffer, int begin, int len) {
-        //TODO: pares float directly from char[]
+    protected float parseFloat(char[] buffer, int begin, int len) throws ParseException {
+        // TODO: parse float directly from char[]
         String str = new String(buffer, begin, len);
-        return Float.valueOf(str);
+        try {
+            return Float.parseFloat(str);
+        } catch (NumberFormatException e) {
+            throw new ParseException(ErrorCode.PARSER_ADM_DATA_PARSER_WRONG_INSTANCE, e, str,
+                    BuiltinType.AFLOAT.getTypeName());
+        }
+    }
+
+    protected void parseInt64(char[] buffer, int begin, int len, AMutableInt64 result) throws ParseException {
+        if (!NumberUtils.parseInt64(buffer, begin, begin + len, StringUtil.getCharArrayAccessor(), result)) {
+            throw new ParseException(ErrorCode.PARSER_ADM_DATA_PARSER_WRONG_INSTANCE, new String(buffer, begin, len),
+                    BuiltinType.AINT64.getTypeName());
+        }
     }
 
     protected int indexOf(char[] buffer, int begin, int len, char target) {
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/AbstractJsonDataParser.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/AbstractJsonDataParser.java
index 2d20cc2..b59dd1c 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/AbstractJsonDataParser.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/AbstractJsonDataParser.java
@@ -329,7 +329,7 @@ public abstract class AbstractJsonDataParser extends AbstractNestedDataParser<AD
                 break;
             case INT:
             case DOUBLE:
-                serailizeNumeric(actualType.getTypeTag(), out);
+                serializeNumeric(actualType.getTypeTag(), out);
                 break;
             case STRING:
                 serializeString(actualType.getTypeTag(), out);
@@ -352,7 +352,7 @@ public abstract class AbstractJsonDataParser extends AbstractNestedDataParser<AD
      * @param out
      * @throws IOException
      */
-    private void serailizeNumeric(ATypeTag numericType, DataOutput out) throws IOException {
+    protected void serializeNumeric(ATypeTag numericType, DataOutput out) throws IOException {
         final ATypeTag typeToUse = numericType == ATypeTag.ANY ? currentToken().getTypeTag() : numericType;
 
         switch (typeToUse) {
@@ -393,7 +393,7 @@ public abstract class AbstractJsonDataParser extends AbstractNestedDataParser<AD
      * @param out
      * @throws IOException
      */
-    private void serializeString(ATypeTag stringVariantType, DataOutput out) throws IOException {
+    protected void serializeString(ATypeTag stringVariantType, DataOutput out) throws IOException {
         char[] buffer = jsonParser.getTextCharacters();
         int begin = jsonParser.getTextOffset();
         int len = jsonParser.getTextLength();
@@ -412,6 +412,18 @@ public abstract class AbstractJsonDataParser extends AbstractNestedDataParser<AD
             case TIME:
                 parseTime(buffer, begin, len, out);
                 break;
+            case YEARMONTHDURATION:
+                parseYearMonthDuration(buffer, begin, len, out);
+                break;
+            case DAYTIMEDURATION:
+                parseDateTimeDuration(buffer, begin, len, out);
+                break;
+            case DURATION:
+                parseDuration(buffer, begin, len, out);
+                break;
+            case UUID:
+                parseUUID(buffer, begin, len, out);
+                break;
             default:
                 throw new RuntimeDataException(ErrorCode.TYPE_UNSUPPORTED, jsonParser.currentToken().toString());
 
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/AbstractNestedDataParser.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/AbstractNestedDataParser.java
index eecbb19..bc15f1e 100644
--- a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/AbstractNestedDataParser.java
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/AbstractNestedDataParser.java
@@ -183,8 +183,10 @@ public abstract class AbstractNestedDataParser<T> extends AbstractDataParser {
     protected boolean isConvertable(ATypeTag parsedTypeTag, ATypeTag definedTypeTag) {
         boolean convertable = parsedTypeTag == ATypeTag.STRING;
 
-        convertable &= definedTypeTag == ATypeTag.UUID || definedTypeTag == ATypeTag.DATE
-                || definedTypeTag == ATypeTag.TIME || definedTypeTag == ATypeTag.DATETIME;
+        convertable &=
+                definedTypeTag == ATypeTag.UUID || definedTypeTag == ATypeTag.DATE || definedTypeTag == ATypeTag.TIME
+                        || definedTypeTag == ATypeTag.DATETIME || definedTypeTag == ATypeTag.YEARMONTHDURATION
+                        || definedTypeTag == ATypeTag.DAYTIMEDURATION || definedTypeTag == ATypeTag.DURATION;
 
         return convertable || ATypeHierarchy.canPromote(parsedTypeTag, definedTypeTag)
                 || ATypeHierarchy.canDemote(parsedTypeTag, definedTypeTag);
diff --git a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/LosslessADMJSONDataParser.java b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/LosslessADMJSONDataParser.java
new file mode 100644
index 0000000..79bca9c
--- /dev/null
+++ b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/LosslessADMJSONDataParser.java
@@ -0,0 +1,302 @@
+/*
+ * 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.asterix.external.parser;
+
+import java.io.DataOutput;
+import java.io.IOException;
+
+import org.apache.asterix.common.exceptions.ErrorCode;
+import org.apache.asterix.common.exceptions.RuntimeDataException;
+import org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm.ATaggedValuePrinter;
+import org.apache.asterix.om.base.ABoolean;
+import org.apache.asterix.om.base.AMissing;
+import org.apache.asterix.om.base.AMutableInt32;
+import org.apache.asterix.om.base.AMutablePoint;
+import org.apache.asterix.om.base.ANull;
+import org.apache.asterix.om.types.ATypeTag;
+import org.apache.asterix.om.types.BuiltinType;
+import org.apache.asterix.om.types.EnumDeserializer;
+import org.apache.asterix.om.utils.RecordUtil;
+import org.apache.hyracks.util.bytes.HexParser;
+
+import com.fasterxml.jackson.core.JsonFactory;
+
+public final class LosslessADMJSONDataParser extends JSONDataParser {
+
+    private AMutablePoint[] polygonPoints;
+
+    public LosslessADMJSONDataParser(JsonFactory jsonFactory) {
+        super(RecordUtil.FULLY_OPEN_RECORD_TYPE, jsonFactory);
+    }
+
+    @Override
+    protected void serializeNumeric(ATypeTag numericType, DataOutput out) throws IOException {
+        super.serializeNumeric(ATypeTag.BIGINT, out);
+    }
+
+    @Override
+    protected void serializeString(ATypeTag stringVariantType, DataOutput out) throws IOException {
+        char[] textChars = jsonParser.getTextCharacters();
+        int textOffset = jsonParser.getTextOffset();
+        int textLength = jsonParser.getTextLength();
+
+        ATypeTag typeToUse = parseTypeTag(textChars, textOffset, textLength, aInt32);
+        if (typeToUse == null) {
+            throw new RuntimeDataException(ErrorCode.RECORD_READER_MALFORMED_INPUT_STREAM);
+        }
+        int parsedLength = aInt32.getIntegerValue();
+        int nonTaggedTextOffset = textOffset + parsedLength;
+        int nonTaggedTextLength = textLength - parsedLength;
+        switch (typeToUse) {
+            case MISSING:
+                missingSerde.serialize(AMissing.MISSING, out);
+                break;
+            case NULL:
+                nullSerde.serialize(ANull.NULL, out);
+                break;
+            case BOOLEAN:
+                parseInt64(textChars, nonTaggedTextOffset, nonTaggedTextLength, aInt64);
+                booleanSerde.serialize(ABoolean.valueOf(aInt64.getLongValue() != 0), out);
+                break;
+            case TINYINT:
+                parseInt64(textChars, nonTaggedTextOffset, nonTaggedTextLength, aInt64);
+                aInt8.setValue((byte) aInt64.getLongValue());
+                int8Serde.serialize(aInt8, out);
+                break;
+            case SMALLINT:
+                parseInt64(textChars, nonTaggedTextOffset, nonTaggedTextLength, aInt64);
+                aInt16.setValue((short) aInt64.getLongValue());
+                int16Serde.serialize(aInt16, out);
+                break;
+            case INTEGER:
+                parseInt64(textChars, nonTaggedTextOffset, nonTaggedTextLength, aInt64);
+                aInt32.setValue((int) aInt64.getLongValue());
+                int32Serde.serialize(aInt32, out);
+                break;
+            case BIGINT:
+                parseInt64(textChars, nonTaggedTextOffset, nonTaggedTextLength, aInt64);
+                int64Serde.serialize(aInt64, out);
+                break;
+            case FLOAT:
+                parseInt64(textChars, nonTaggedTextOffset, nonTaggedTextLength, aInt64);
+                aFloat.setValue(Float.intBitsToFloat((int) aInt64.getLongValue()));
+                floatSerde.serialize(aFloat, out);
+                break;
+            case DOUBLE:
+                parseInt64(textChars, nonTaggedTextOffset, nonTaggedTextLength, aInt64);
+                aDouble.setValue(Double.longBitsToDouble(aInt64.getLongValue()));
+                doubleSerde.serialize(aDouble, out);
+                break;
+            case TIME:
+                parseInt64(textChars, nonTaggedTextOffset, nonTaggedTextLength, aInt64);
+                aTime.setValue((int) aInt64.getLongValue());
+                timeSerde.serialize(aTime, out);
+                break;
+            case DATE:
+                parseInt64(textChars, nonTaggedTextOffset, nonTaggedTextLength, aInt64);
+                aDate.setValue((int) aInt64.getLongValue());
+                dateSerde.serialize(aDate, out);
+                break;
+            case DATETIME:
+                parseInt64(textChars, nonTaggedTextOffset, nonTaggedTextLength, aInt64);
+                aDateTime.setValue(aInt64.getLongValue());
+                datetimeSerde.serialize(aDateTime, out);
+                break;
+            case YEARMONTHDURATION:
+                parseInt64(textChars, nonTaggedTextOffset, nonTaggedTextLength, aInt64);
+                aYearMonthDuration.setMonths((int) aInt64.getLongValue());
+                yearMonthDurationSerde.serialize(aYearMonthDuration, out);
+                break;
+            case DAYTIMEDURATION:
+                parseInt64(textChars, nonTaggedTextOffset, nonTaggedTextLength, aInt64);
+                aDayTimeDuration.setMilliseconds(aInt64.getLongValue());
+                dayTimeDurationSerde.serialize(aDayTimeDuration, out);
+                break;
+            case DURATION:
+                int delimIdx = findDelim(textChars, nonTaggedTextOffset, nonTaggedTextLength, BuiltinType.ADURATION);
+                parseInt64(textChars, nonTaggedTextOffset, delimIdx - nonTaggedTextOffset, aInt64);
+                int months = (int) aInt64.getLongValue();
+                parseInt64(textChars, delimIdx + 1, textLength - delimIdx - 1, aInt64);
+                long millis = aInt64.getLongValue();
+                aDuration.setValue(months, millis);
+                durationSerde.serialize(aDuration, out);
+                break;
+            case UUID:
+                aUUID.parseUUIDString(textChars, nonTaggedTextOffset, nonTaggedTextLength);
+                uuidSerde.serialize(aUUID, out);
+                break;
+            case STRING:
+                parseString(textChars, nonTaggedTextOffset, nonTaggedTextLength, out);
+                break;
+            case BINARY:
+                parseBase64BinaryString(textChars, nonTaggedTextOffset, nonTaggedTextLength, out);
+                break;
+            case POINT:
+                delimIdx = findDelim(textChars, nonTaggedTextOffset, nonTaggedTextLength, BuiltinType.APOINT);
+                parseInt64(textChars, nonTaggedTextOffset, delimIdx - nonTaggedTextOffset, aInt64);
+                double x = Double.longBitsToDouble(aInt64.getLongValue());
+                parseInt64(textChars, delimIdx + 1, textLength - delimIdx - 1, aInt64);
+                double y = Double.longBitsToDouble(aInt64.getLongValue());
+                aPoint.setValue(x, y);
+                pointSerde.serialize(aPoint, out);
+                break;
+            case POINT3D:
+                delimIdx = findDelim(textChars, nonTaggedTextOffset, nonTaggedTextLength, BuiltinType.APOINT3D);
+                parseInt64(textChars, nonTaggedTextOffset, delimIdx - nonTaggedTextOffset, aInt64);
+                x = Double.longBitsToDouble(aInt64.getLongValue());
+                int delimIdx2 = findDelim(textChars, delimIdx + 1, textLength - delimIdx - 1, BuiltinType.APOINT3D);
+                parseInt64(textChars, delimIdx + 1, delimIdx2 - delimIdx - 1, aInt64);
+                y = Double.longBitsToDouble(aInt64.getLongValue());
+                parseInt64(textChars, delimIdx2 + 1, textLength - delimIdx2 - 1, aInt64);
+                double z = Double.longBitsToDouble(aInt64.getLongValue());
+                aPoint3D.setValue(x, y, z);
+                point3DSerde.serialize(aPoint3D, out);
+                break;
+            case CIRCLE:
+                delimIdx = findDelim(textChars, nonTaggedTextOffset, nonTaggedTextLength, BuiltinType.ACIRCLE);
+                parseInt64(textChars, nonTaggedTextOffset, delimIdx - nonTaggedTextOffset, aInt64);
+                x = Double.longBitsToDouble(aInt64.getLongValue());
+                delimIdx2 = findDelim(textChars, delimIdx + 1, textLength - delimIdx - 1, BuiltinType.ACIRCLE);
+                parseInt64(textChars, delimIdx + 1, delimIdx2 - delimIdx - 1, aInt64);
+                y = Double.longBitsToDouble(aInt64.getLongValue());
+                parseInt64(textChars, delimIdx2 + 1, textLength - delimIdx2 - 1, aInt64);
+                z = Double.longBitsToDouble(aInt64.getLongValue());
+                aPoint.setValue(x, y);
+                aCircle.setValue(aPoint, z);
+                circleSerde.serialize(aCircle, out);
+                break;
+            case LINE:
+                delimIdx = findDelim(textChars, nonTaggedTextOffset, nonTaggedTextLength, BuiltinType.ALINE);
+                parseInt64(textChars, nonTaggedTextOffset, delimIdx - nonTaggedTextOffset, aInt64);
+                x = Double.longBitsToDouble(aInt64.getLongValue());
+                delimIdx2 = findDelim(textChars, delimIdx + 1, textLength - delimIdx - 1, BuiltinType.ALINE);
+                parseInt64(textChars, delimIdx + 1, delimIdx2 - delimIdx - 1, aInt64);
+                y = Double.longBitsToDouble(aInt64.getLongValue());
+                int delimIdx3 = findDelim(textChars, delimIdx2 + 1, textLength - delimIdx2 - 1, BuiltinType.ALINE);
+                parseInt64(textChars, delimIdx2 + 1, delimIdx3 - delimIdx2 - 1, aInt64);
+                double x2 = Double.longBitsToDouble(aInt64.getLongValue());
+                parseInt64(textChars, delimIdx3 + 1, textLength - delimIdx3 - 1, aInt64);
+                double y2 = Double.longBitsToDouble(aInt64.getLongValue());
+                aPoint.setValue(x, y);
+                aPoint2.setValue(x2, y2);
+                aLine.setValue(aPoint, aPoint2);
+                lineSerde.serialize(aLine, out);
+                break;
+            case RECTANGLE:
+                delimIdx = findDelim(textChars, nonTaggedTextOffset, nonTaggedTextLength, BuiltinType.ARECTANGLE);
+                parseInt64(textChars, nonTaggedTextOffset, delimIdx - nonTaggedTextOffset, aInt64);
+                x = Double.longBitsToDouble(aInt64.getLongValue());
+                delimIdx2 = findDelim(textChars, delimIdx + 1, textLength - delimIdx - 1, BuiltinType.ARECTANGLE);
+                parseInt64(textChars, delimIdx + 1, delimIdx2 - delimIdx - 1, aInt64);
+                y = Double.longBitsToDouble(aInt64.getLongValue());
+                delimIdx3 = findDelim(textChars, delimIdx2 + 1, textLength - delimIdx2 - 1, BuiltinType.ARECTANGLE);
+                parseInt64(textChars, delimIdx2 + 1, delimIdx3 - delimIdx2 - 1, aInt64);
+                x2 = Double.longBitsToDouble(aInt64.getLongValue());
+                parseInt64(textChars, delimIdx3 + 1, textLength - delimIdx3 - 1, aInt64);
+                y2 = Double.longBitsToDouble(aInt64.getLongValue());
+                aPoint.setValue(x, y);
+                aPoint2.setValue(x2, y2);
+                aRectangle.setValue(aPoint, aPoint2);
+                rectangleSerde.serialize(aRectangle, out);
+                break;
+            case POLYGON:
+                delimIdx = findDelim(textChars, nonTaggedTextOffset, nonTaggedTextLength, BuiltinType.APOLYGON);
+                parseInt64(textChars, nonTaggedTextOffset, delimIdx - nonTaggedTextOffset, aInt64);
+                int numPoints = (int) aInt64.getLongValue();
+                if (polygonPoints == null || polygonPoints.length != numPoints) {
+                    polygonPoints = new AMutablePoint[numPoints];
+                    for (int i = 0; i < numPoints; i++) {
+                        polygonPoints[i] = new AMutablePoint(0, 0);
+                    }
+                }
+                for (int i = 0; i < numPoints; i++) {
+                    delimIdx2 = findDelim(textChars, delimIdx + 1, textLength - delimIdx - 1, BuiltinType.APOLYGON);
+                    parseInt64(textChars, delimIdx + 1, delimIdx2 - delimIdx - 1, aInt64);
+                    x = Double.longBitsToDouble(aInt64.getLongValue());
+                    if (i < numPoints - 1) {
+                        delimIdx3 =
+                                findDelim(textChars, delimIdx2 + 1, textLength - delimIdx2 - 1, BuiltinType.APOLYGON);
+                        parseInt64(textChars, delimIdx2 + 1, delimIdx3 - delimIdx2 - 1, aInt64);
+                        delimIdx = delimIdx3;
+                    } else {
+                        parseInt64(textChars, delimIdx2 + 1, textLength - delimIdx2 - 1, aInt64);
+                    }
+                    y = Double.longBitsToDouble(aInt64.getLongValue());
+                    polygonPoints[i].setValue(x, y);
+                }
+                aPolygon.setValue(polygonPoints);
+                polygonSerde.serialize(aPolygon, out);
+                break;
+            default:
+                throw new RuntimeDataException(ErrorCode.TYPE_UNSUPPORTED, "", typeToUse.toString());
+        }
+    }
+
+    private static ATypeTag parseTypeTag(char[] textChars, int textOffset, int textLength,
+            AMutableInt32 outParsedLength) {
+        if (textLength == 0) {
+            // empty string
+            outParsedLength.setValue(0);
+            return ATypeTag.STRING;
+        }
+        if (textChars[textOffset] == ATaggedValuePrinter.DELIMITER) {
+            // any string
+            outParsedLength.setValue(1);
+            return ATypeTag.STRING;
+        }
+        // any type
+        int typeTagLength = 2;
+        if (textLength < typeTagLength) {
+            return null;
+        }
+        byte typeTagByte;
+        try {
+            typeTagByte = HexParser.getByteFromValidHexChars(textChars[textOffset], textChars[textOffset + 1]);
+        } catch (IllegalArgumentException e) {
+            return null;
+        }
+        ATypeTag typeTag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(typeTagByte);
+        if (typeTag == null) {
+            return null;
+        }
+        if (typeTag == ATypeTag.MISSING || typeTag == ATypeTag.NULL) {
+            outParsedLength.setValue(typeTagLength);
+            return typeTag;
+        }
+        int delimiterLength = 1;
+        if (textLength < typeTagLength + delimiterLength) {
+            return null;
+        }
+        if (textChars[textOffset + typeTagLength] != ATaggedValuePrinter.DELIMITER) {
+            return null;
+        }
+        outParsedLength.setValue(typeTagLength + delimiterLength);
+        return typeTag;
+    }
+
+    private int findDelim(char[] text, int offset, int len, BuiltinType type) throws ParseException {
+        try {
+            return indexOf(text, offset, len, ATaggedValuePrinter.DELIMITER);
+        } catch (IllegalArgumentException e) {
+            throw new ParseException(ErrorCode.PARSER_ADM_DATA_PARSER_WRONG_INSTANCE, new String(text, offset, len),
+                    type.getTypeName());
+        }
+    }
+}
diff --git a/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/parser/test/LosslessADMJSONDataParserTest.java b/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/parser/test/LosslessADMJSONDataParserTest.java
new file mode 100644
index 0000000..e457ea2
--- /dev/null
+++ b/asterixdb/asterix-external-data/src/test/java/org/apache/asterix/external/parser/test/LosslessADMJSONDataParserTest.java
@@ -0,0 +1,287 @@
+/*
+ * 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.asterix.external.parser.test;
+
+import static org.apache.asterix.om.types.AOrderedListType.FULL_OPEN_ORDEREDLIST_TYPE;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.PrintStream;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Objects;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.asterix.dataflow.data.nontagged.serde.AObjectSerializerDeserializer;
+import org.apache.asterix.external.parser.LosslessADMJSONDataParser;
+import org.apache.asterix.formats.nontagged.LosslessADMJSONPrinterFactoryProvider;
+import org.apache.asterix.formats.nontagged.SerializerDeserializerProvider;
+import org.apache.asterix.om.base.ABinary;
+import org.apache.asterix.om.base.ABoolean;
+import org.apache.asterix.om.base.ACircle;
+import org.apache.asterix.om.base.ADate;
+import org.apache.asterix.om.base.ADateTime;
+import org.apache.asterix.om.base.ADayTimeDuration;
+import org.apache.asterix.om.base.ADouble;
+import org.apache.asterix.om.base.ADuration;
+import org.apache.asterix.om.base.AFloat;
+import org.apache.asterix.om.base.AInt16;
+import org.apache.asterix.om.base.AInt32;
+import org.apache.asterix.om.base.AInt64;
+import org.apache.asterix.om.base.AInt8;
+import org.apache.asterix.om.base.ALine;
+import org.apache.asterix.om.base.AMissing;
+import org.apache.asterix.om.base.AMutableUUID;
+import org.apache.asterix.om.base.ANull;
+import org.apache.asterix.om.base.AOrderedList;
+import org.apache.asterix.om.base.APoint;
+import org.apache.asterix.om.base.APoint3D;
+import org.apache.asterix.om.base.APolygon;
+import org.apache.asterix.om.base.ARecord;
+import org.apache.asterix.om.base.ARectangle;
+import org.apache.asterix.om.base.AString;
+import org.apache.asterix.om.base.ATime;
+import org.apache.asterix.om.base.AUUID;
+import org.apache.asterix.om.base.AUnorderedList;
+import org.apache.asterix.om.base.AYearMonthDuration;
+import org.apache.asterix.om.base.IAObject;
+import org.apache.asterix.om.types.ARecordType;
+import org.apache.asterix.om.types.ATypeTag;
+import org.apache.asterix.om.types.AUnorderedListType;
+import org.apache.asterix.om.types.IAType;
+import org.apache.hyracks.algebricks.data.IPrinter;
+import org.apache.hyracks.api.dataflow.value.ISerializerDeserializer;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.apache.hyracks.data.std.util.ByteArrayAccessibleInputStream;
+import org.apache.hyracks.data.std.util.ByteArrayAccessibleOutputStream;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import com.fasterxml.jackson.core.JsonFactory;
+
+@RunWith(Parameterized.class)
+public class LosslessADMJSONDataParserTest {
+
+    static final IAObject[] PRIMITIVE_VALUES = new IAObject[] {
+            //
+            AMissing.MISSING,
+            //
+            ANull.NULL,
+            //
+            ABoolean.TRUE,
+            //
+            ABoolean.FALSE,
+            //
+            new AInt8((byte) 8),
+            //
+            new AInt8((byte) -8),
+            //
+            new AInt16((short) 16),
+            //
+            new AInt16((short) -16),
+            //
+            new AInt32((short) 32),
+            //
+            new AInt32((short) -32),
+            //
+            new AInt64(64),
+            //
+            new AInt64(-64),
+            //
+            new AFloat(1.5f),
+            //
+            new AFloat(-1.5f),
+            //
+            new AFloat(Float.POSITIVE_INFINITY),
+            //
+            new AFloat(Float.NEGATIVE_INFINITY),
+            //
+            new AFloat(Float.NaN),
+            //
+            new ADouble(1.5d),
+            //
+            new ADouble(-1.5d),
+            //
+            new ADouble(Double.POSITIVE_INFINITY),
+            //
+            new ADouble(Double.NEGATIVE_INFINITY),
+            //
+            new ADouble(Double.NaN),
+            //
+            new AString(""),
+            //
+            new AString(" "),
+            //
+            new AString(":"),
+            //
+            new AString("hello"),
+            //
+            new ADate(2),
+            //
+            new ATime((int) TimeUnit.HOURS.toMillis(3)),
+            //
+            new ADateTime(TimeUnit.DAYS.toMillis(4)),
+            //
+            new AYearMonthDuration(2),
+            //
+            new ADayTimeDuration((int) TimeUnit.HOURS.toMillis(3)),
+            //
+            new ADuration(4, (int) TimeUnit.HOURS.toMillis(5)),
+            //
+            new ABinary(new byte[] {}),
+            //
+            new ABinary(new byte[] { 1, 2, 3, 4 }),
+            //
+            createUUID(UUID.randomUUID()),
+            //
+            new APoint(1.5, -2.5),
+            //
+            new APoint3D(-1.5, 2.5, 3.5),
+            //
+            new ACircle(new APoint(1.5, -2.5), 3.5),
+            //
+            new ALine(new APoint(-1.5, -2.5), new APoint(3.5, 4.5)),
+            //
+            new ARectangle(new APoint(-1.5, -2.5), new APoint(3.5, 4.5)),
+            //
+            new APolygon(new APoint[] { new APoint(-1.5, -2.5), new APoint(-1.5, 2.5), new APoint(1.5, 2.5),
+                    new APoint(1.5, -2.5) }) };
+    private final String label;
+    private final IAObject inValue;
+    private final IAObject expectedOutValue;
+
+    public LosslessADMJSONDataParserTest(String label, IAObject inValue, IAObject expectedOutValue) {
+        this.label = label;
+        this.inValue = Objects.requireNonNull(inValue);
+        this.expectedOutValue = expectedOutValue == null ? inValue : expectedOutValue;
+    }
+
+    @Parameterized.Parameters(name = "LosslessADMJSONDataParserTest {index}: {0}")
+    public static Collection<Object[]> tests() throws Exception {
+        List<Object[]> tests = new ArrayList<>();
+        testsForPrimitives(tests);
+        testsForArrays(tests);
+        testsForObjects(tests);
+        return tests;
+    }
+
+    private static void testsForPrimitives(List<Object[]> outTests) {
+        for (IAObject v : PRIMITIVE_VALUES) {
+            outTests.add(testcase(v));
+        }
+    }
+
+    private static void testsForArrays(List<Object[]> outTests) {
+        for (IAObject v1 : PRIMITIVE_VALUES) {
+            for (IAObject v2 : PRIMITIVE_VALUES) {
+                // array of primitives
+                AOrderedList ol1 = new AOrderedList(FULL_OPEN_ORDEREDLIST_TYPE, Arrays.asList(v1, v2));
+                outTests.add(testcase(ol1));
+                // multiset of primitives (printed as array)
+                AUnorderedList ul1 =
+                        new AUnorderedList(AUnorderedListType.FULLY_OPEN_UNORDEREDLIST_TYPE, Arrays.asList(v1, v2));
+                outTests.add(testcase(ul1, ol1));
+                // array of arrays
+                AOrderedList ol2 = new AOrderedList(FULL_OPEN_ORDEREDLIST_TYPE, Arrays.asList(v2, v1));
+                AOrderedList ol3 = new AOrderedList(FULL_OPEN_ORDEREDLIST_TYPE, Arrays.asList(ol1, ol2));
+                outTests.add(testcase(ol3));
+            }
+        }
+    }
+
+    private static void testsForObjects(List<Object[]> outTests) {
+        // flat
+        List<String> fieldNames = new ArrayList<>();
+        List<IAType> fieldTypes = new ArrayList<>();
+        List<IAObject> fieldValues = new ArrayList<>();
+        for (IAObject v : PRIMITIVE_VALUES) {
+            if (v.getType().getTypeTag() != ATypeTag.BIGINT) {
+                continue;
+            }
+            fieldNames.add("f" + fieldNames.size());
+            fieldTypes.add(v.getType());
+            fieldValues.add(v);
+        }
+        ARecordType rt0 =
+                new ARecordType("rt0", fieldNames.toArray(new String[0]), fieldTypes.toArray(new IAType[0]), true);
+        ARecord r0 = new ARecord(rt0, fieldValues.toArray(new IAObject[0]));
+        outTests.add(testcase(r0));
+
+        // nested
+        ARecordType rt1 = new ARecordType("rt1", new String[] { "n1", "n2" }, new IAType[] { rt0, rt0 }, true);
+        ARecord r1 = new ARecord(rt1, new IAObject[] { r0, r0 });
+        outTests.add(testcase(r1));
+    }
+
+    private static Object[] testcase(IAObject v) {
+        return testcase(v, v);
+    }
+
+    private static Object[] testcase(IAObject v, IAObject expectedOutValue) {
+        return new Object[] { String.format("%s(%s)", v.getType().getTypeName(), v), v, expectedOutValue };
+    }
+
+    private static AUUID createUUID(UUID uuid) {
+        try {
+            AMutableUUID m = new AMutableUUID();
+            char[] text = uuid.toString().toCharArray();
+            m.parseUUIDString(text, 0, text.length);
+            return m;
+        } catch (HyracksDataException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void test() throws Exception {
+        ByteArrayAccessibleOutputStream baosInSer = new ByteArrayAccessibleOutputStream();
+        ISerializerDeserializer serde =
+                SerializerDeserializerProvider.INSTANCE.getSerializerDeserializer(inValue.getType());
+        serde.serialize(inValue, new DataOutputStream(baosInSer));
+
+        ByteArrayAccessibleOutputStream baosPrint = new ByteArrayAccessibleOutputStream();
+        IPrinter printer =
+                LosslessADMJSONPrinterFactoryProvider.INSTANCE.getPrinterFactory(inValue.getType()).createPrinter();
+        printer.print(baosInSer.getByteArray(), 0, baosInSer.getLength(),
+                new PrintStream(baosPrint, true, StandardCharsets.UTF_8));
+
+        ByteArrayAccessibleOutputStream baosParse = new ByteArrayAccessibleOutputStream();
+        LosslessADMJSONDataParser lp = new LosslessADMJSONDataParser(new JsonFactory());
+        lp.setInputStream(new ByteArrayAccessibleInputStream(baosPrint.getByteArray(), 0, baosPrint.getLength()));
+        lp.parseAnyValue(new DataOutputStream(baosParse));
+
+        IAObject outValue = AObjectSerializerDeserializer.INSTANCE.deserialize(new DataInputStream(
+                new ByteArrayAccessibleInputStream(baosParse.getByteArray(), 0, baosParse.getLength())));
+
+        if (!expectedOutValue.deepEqual(outValue)) {
+            Assert.fail(String.format(
+                    "%s print/parse test failed. In value: %s, Expected out value: %s, Actual out value: %s, Encoded value: %s",
+                    label, inValue, expectedOutValue, outValue,
+                    new String(baosPrint.getByteArray(), 0, baosPrint.getLength(), StandardCharsets.UTF_8)));
+        }
+    }
+}
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/PrintTools.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/PrintTools.java
index a7eef65..b337777 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/PrintTools.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/PrintTools.java
@@ -293,9 +293,15 @@ public class PrintTools {
 
     public static void writeUTF8StringAsJSON(byte[] b, int s, int l, OutputStream os) throws IOException {
         int utfLength = UTF8StringUtil.getUTFLength(b, s);
+        os.write('"');
+        writeUTF8StringAsJSONUnquoted(b, s, l, utfLength, os);
+        os.write('"');
+    }
+
+    public static void writeUTF8StringAsJSONUnquoted(byte[] b, int s, int l, int utfLength, OutputStream os)
+            throws IOException {
         int position = s + UTF8StringUtil.getNumBytesToStoreLength(utfLength); // skip 2 bytes containing string size
         int maxPosition = position + utfLength;
-        os.write('"');
         while (position < maxPosition) {
             char c = UTF8StringUtil.charAt(b, position);
             int sz = UTF8StringUtil.charSize(b, position);
@@ -385,7 +391,6 @@ public class PrintTools {
                     break;
             }
         }
-        os.write('\"');
     }
 
     private static void writeUEscape(OutputStream os, char c) throws IOException {
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/adm/AUUIDPrinterFactory.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/adm/AUUIDPrinterFactory.java
index 41da3bd..739b653 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/adm/AUUIDPrinterFactory.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/adm/AUUIDPrinterFactory.java
@@ -19,11 +19,13 @@
 
 package org.apache.asterix.dataflow.data.nontagged.printers.adm;
 
+import java.io.IOException;
 import java.io.PrintStream;
 
 import org.apache.asterix.om.base.AUUID;
 import org.apache.hyracks.algebricks.data.IPrinter;
 import org.apache.hyracks.algebricks.data.IPrinterFactory;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
 
 public class AUUIDPrinterFactory implements IPrinterFactory {
 
@@ -32,10 +34,13 @@ public class AUUIDPrinterFactory implements IPrinterFactory {
     public static final AUUIDPrinterFactory INSTANCE = new AUUIDPrinterFactory();
 
     public static final IPrinter PRINTER = (byte[] b, int s, int l, PrintStream ps) -> {
-        StringBuilder buf = new StringBuilder(AUUID.UUID_CHARS + 8);
-        buf.append("uuid(\"");
-        AUUID.appendLiteralOnly(b, s + 1, buf).append("\")");
-        ps.print(buf.toString());
+        try {
+            ps.append("uuid(\"");
+            AUUID.appendLiteralOnly(b, s + 1, ps);
+            ps.append("\")");
+        } catch (IOException e) {
+            throw HyracksDataException.create(e);
+        }
     };
 
     @Override
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/csv/AUUIDPrinterFactory.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/csv/AUUIDPrinterFactory.java
index e4ecfea..0c8ae87 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/csv/AUUIDPrinterFactory.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/csv/AUUIDPrinterFactory.java
@@ -19,11 +19,13 @@
 
 package org.apache.asterix.dataflow.data.nontagged.printers.csv;
 
+import java.io.IOException;
 import java.io.PrintStream;
 
 import org.apache.asterix.om.base.AUUID;
 import org.apache.hyracks.algebricks.data.IPrinter;
 import org.apache.hyracks.algebricks.data.IPrinterFactory;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
 
 public class AUUIDPrinterFactory implements IPrinterFactory {
 
@@ -32,10 +34,13 @@ public class AUUIDPrinterFactory implements IPrinterFactory {
     public static final AUUIDPrinterFactory INSTANCE = new AUUIDPrinterFactory();
 
     public static final IPrinter PRINTER = (byte[] b, int s, int l, PrintStream ps) -> {
-        StringBuilder buf = new StringBuilder(AUUID.UUID_CHARS + 2);
-        buf.append('"');
-        AUUID.appendLiteralOnly(b, s + 1, buf).append('"');
-        ps.print(buf.toString());
+        try {
+            ps.append('"');
+            AUUID.appendLiteralOnly(b, s + 1, ps);
+            ps.append('"');
+        } catch (IOException e) {
+            throw HyracksDataException.create(e);
+        }
     };
 
     @Override
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java
index f1c853f..b364be9 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java
@@ -19,11 +19,13 @@
 
 package org.apache.asterix.dataflow.data.nontagged.printers.json.clean;
 
+import java.io.IOException;
 import java.io.PrintStream;
 
 import org.apache.asterix.om.base.AUUID;
 import org.apache.hyracks.algebricks.data.IPrinter;
 import org.apache.hyracks.algebricks.data.IPrinterFactory;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
 
 public class AUUIDPrinterFactory implements IPrinterFactory {
 
@@ -32,10 +34,13 @@ public class AUUIDPrinterFactory implements IPrinterFactory {
     public static final AUUIDPrinterFactory INSTANCE = new AUUIDPrinterFactory();
 
     public static final IPrinter PRINTER = (byte[] b, int s, int l, PrintStream ps) -> {
-        StringBuilder buf = new StringBuilder(AUUID.UUID_CHARS + 2);
-        buf.append('"');
-        AUUID.appendLiteralOnly(b, s + 1, buf).append('"');
-        ps.print(buf.toString());
+        try {
+            ps.append('"');
+            AUUID.appendLiteralOnly(b, s + 1, ps);
+            ps.append('"');
+        } catch (IOException e) {
+            throw HyracksDataException.create(e);
+        }
     };
 
     @Override
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/lossless/AUUIDPrinterFactory.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/lossless/AUUIDPrinterFactory.java
index 2366a98..388fc913 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/lossless/AUUIDPrinterFactory.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/lossless/AUUIDPrinterFactory.java
@@ -19,11 +19,13 @@
 
 package org.apache.asterix.dataflow.data.nontagged.printers.json.lossless;
 
+import java.io.IOException;
 import java.io.PrintStream;
 
 import org.apache.asterix.om.base.AUUID;
 import org.apache.hyracks.algebricks.data.IPrinter;
 import org.apache.hyracks.algebricks.data.IPrinterFactory;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
 
 public class AUUIDPrinterFactory implements IPrinterFactory {
 
@@ -32,10 +34,13 @@ public class AUUIDPrinterFactory implements IPrinterFactory {
     public static final AUUIDPrinterFactory INSTANCE = new AUUIDPrinterFactory();
 
     public static final IPrinter PRINTER = (byte[] b, int s, int l, PrintStream ps) -> {
-        StringBuilder buf = new StringBuilder(AUUID.UUID_CHARS + 2);
-        buf.append('"');
-        AUUID.appendLiteralOnly(b, s + 1, buf).append('"');
-        ps.print(buf.toString());
+        try {
+            ps.append('"');
+            AUUID.appendLiteralOnly(b, s + 1, ps);
+            ps.append('"');
+        } catch (IOException e) {
+            throw HyracksDataException.create(e);
+        }
     };
 
     @Override
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/ABinaryPrinterFactory.java
similarity index 59%
copy from asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java
copy to asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/ABinaryPrinterFactory.java
index f1c853f..3c18792 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/ABinaryPrinterFactory.java
@@ -17,25 +17,28 @@
  * under the License.
  */
 
-package org.apache.asterix.dataflow.data.nontagged.printers.json.clean;
+package org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm;
 
-import java.io.PrintStream;
+import java.io.IOException;
 
-import org.apache.asterix.om.base.AUUID;
 import org.apache.hyracks.algebricks.data.IPrinter;
 import org.apache.hyracks.algebricks.data.IPrinterFactory;
+import org.apache.hyracks.data.std.primitive.ByteArrayPointable;
+import org.apache.hyracks.util.bytes.Base64Printer;
 
-public class AUUIDPrinterFactory implements IPrinterFactory {
+public class ABinaryPrinterFactory implements IPrinterFactory {
 
     private static final long serialVersionUID = 1L;
 
-    public static final AUUIDPrinterFactory INSTANCE = new AUUIDPrinterFactory();
+    public static final ABinaryPrinterFactory INSTANCE = new ABinaryPrinterFactory();
 
-    public static final IPrinter PRINTER = (byte[] b, int s, int l, PrintStream ps) -> {
-        StringBuilder buf = new StringBuilder(AUUID.UUID_CHARS + 2);
-        buf.append('"');
-        AUUID.appendLiteralOnly(b, s + 1, buf).append('"');
-        ps.print(buf.toString());
+    public static final IPrinter PRINTER = new ATaggedValuePrinter() {
+        @Override
+        protected void printNonTaggedValue(byte[] b, int s, int l, java.io.PrintStream ps) throws IOException {
+            int validLength = ByteArrayPointable.getContentLength(b, s + 1);
+            int start = s + 1 + ByteArrayPointable.getNumberBytesToStoreMeta(validLength);
+            Base64Printer.printBase64Binary(b, start, validLength, ps);
+        }
     };
 
     @Override
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/ABooleanPrinterFactory.java
similarity index 70%
copy from asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java
copy to asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/ABooleanPrinterFactory.java
index f1c853f..8984cad 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/ABooleanPrinterFactory.java
@@ -16,27 +16,25 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-
-package org.apache.asterix.dataflow.data.nontagged.printers.json.clean;
+package org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm;
 
 import java.io.PrintStream;
 
-import org.apache.asterix.om.base.AUUID;
+import org.apache.asterix.dataflow.data.nontagged.serde.ABooleanSerializerDeserializer;
 import org.apache.hyracks.algebricks.data.IPrinter;
 import org.apache.hyracks.algebricks.data.IPrinterFactory;
 
-public class AUUIDPrinterFactory implements IPrinterFactory {
+/**
+ * Boolean value is printed as JSON boolean.
+ */
+public class ABooleanPrinterFactory implements IPrinterFactory {
 
     private static final long serialVersionUID = 1L;
 
-    public static final AUUIDPrinterFactory INSTANCE = new AUUIDPrinterFactory();
+    public static final ABooleanPrinterFactory INSTANCE = new ABooleanPrinterFactory();
 
-    public static final IPrinter PRINTER = (byte[] b, int s, int l, PrintStream ps) -> {
-        StringBuilder buf = new StringBuilder(AUUID.UUID_CHARS + 2);
-        buf.append('"');
-        AUUID.appendLiteralOnly(b, s + 1, buf).append('"');
-        ps.print(buf.toString());
-    };
+    public static final IPrinter PRINTER =
+            (byte[] b, int s, int l, PrintStream ps) -> ps.print(ABooleanSerializerDeserializer.getBoolean(b, s + 1));
 
     @Override
     public IPrinter createPrinter() {
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/ACirclePrinterFactory.java
similarity index 52%
copy from asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java
copy to asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/ACirclePrinterFactory.java
index f1c853f..323c5d6 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/ACirclePrinterFactory.java
@@ -17,25 +17,33 @@
  * under the License.
  */
 
-package org.apache.asterix.dataflow.data.nontagged.printers.json.clean;
+package org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm;
 
-import java.io.PrintStream;
+import java.io.IOException;
 
-import org.apache.asterix.om.base.AUUID;
+import org.apache.asterix.dataflow.data.nontagged.Coordinate;
+import org.apache.asterix.dataflow.data.nontagged.serde.ACircleSerializerDeserializer;
 import org.apache.hyracks.algebricks.data.IPrinter;
 import org.apache.hyracks.algebricks.data.IPrinterFactory;
 
-public class AUUIDPrinterFactory implements IPrinterFactory {
+public class ACirclePrinterFactory implements IPrinterFactory {
 
     private static final long serialVersionUID = 1L;
 
-    public static final AUUIDPrinterFactory INSTANCE = new AUUIDPrinterFactory();
-
-    public static final IPrinter PRINTER = (byte[] b, int s, int l, PrintStream ps) -> {
-        StringBuilder buf = new StringBuilder(AUUID.UUID_CHARS + 2);
-        buf.append('"');
-        AUUID.appendLiteralOnly(b, s + 1, buf).append('"');
-        ps.print(buf.toString());
+    public static final ACirclePrinterFactory INSTANCE = new ACirclePrinterFactory();
+
+    public static final IPrinter PRINTER = new ATaggedValuePrinter() {
+        @Override
+        protected void printNonTaggedValue(byte[] b, int s, int l, java.io.PrintStream ps) throws IOException {
+            int offsetX = ACircleSerializerDeserializer.getCenterPointCoordinateOffset(Coordinate.X);
+            int offsetY = ACircleSerializerDeserializer.getCenterPointCoordinateOffset(Coordinate.Y);
+            int offsetR = ACircleSerializerDeserializer.getRadiusOffset();
+            printDouble(b, s + 1 + offsetX, ps);
+            printDelimiter(ps);
+            printDouble(b, s + 1 + offsetY, ps);
+            printDelimiter(ps);
+            printDouble(b, s + 1 + offsetR, ps);
+        }
     };
 
     @Override
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/ADatePrinterFactory.java
similarity index 70%
copy from asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java
copy to asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/ADatePrinterFactory.java
index f1c853f..590ae4f 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/ADatePrinterFactory.java
@@ -16,26 +16,23 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+package org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm;
 
-package org.apache.asterix.dataflow.data.nontagged.printers.json.clean;
-
-import java.io.PrintStream;
-
-import org.apache.asterix.om.base.AUUID;
+import org.apache.asterix.dataflow.data.nontagged.serde.ADateSerializerDeserializer;
 import org.apache.hyracks.algebricks.data.IPrinter;
 import org.apache.hyracks.algebricks.data.IPrinterFactory;
 
-public class AUUIDPrinterFactory implements IPrinterFactory {
+public class ADatePrinterFactory implements IPrinterFactory {
 
     private static final long serialVersionUID = 1L;
 
-    public static final AUUIDPrinterFactory INSTANCE = new AUUIDPrinterFactory();
+    public static final ADatePrinterFactory INSTANCE = new ADatePrinterFactory();
 
-    public static final IPrinter PRINTER = (byte[] b, int s, int l, PrintStream ps) -> {
-        StringBuilder buf = new StringBuilder(AUUID.UUID_CHARS + 2);
-        buf.append('"');
-        AUUID.appendLiteralOnly(b, s + 1, buf).append('"');
-        ps.print(buf.toString());
+    public static final IPrinter PRINTER = new ATaggedValuePrinter() {
+        @Override
+        protected void printNonTaggedValue(byte[] b, int s, int l, java.io.PrintStream ps) {
+            ps.print(ADateSerializerDeserializer.getChronon(b, s + 1));
+        }
     };
 
     @Override
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/ADateTimePrinterFactory.java
similarity index 68%
copy from asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java
copy to asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/ADateTimePrinterFactory.java
index f1c853f..4ba055b 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/ADateTimePrinterFactory.java
@@ -16,26 +16,23 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+package org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm;
 
-package org.apache.asterix.dataflow.data.nontagged.printers.json.clean;
-
-import java.io.PrintStream;
-
-import org.apache.asterix.om.base.AUUID;
+import org.apache.asterix.dataflow.data.nontagged.serde.ADateTimeSerializerDeserializer;
 import org.apache.hyracks.algebricks.data.IPrinter;
 import org.apache.hyracks.algebricks.data.IPrinterFactory;
 
-public class AUUIDPrinterFactory implements IPrinterFactory {
+public class ADateTimePrinterFactory implements IPrinterFactory {
 
     private static final long serialVersionUID = 1L;
 
-    public static final AUUIDPrinterFactory INSTANCE = new AUUIDPrinterFactory();
+    public static final ADateTimePrinterFactory INSTANCE = new ADateTimePrinterFactory();
 
-    public static final IPrinter PRINTER = (byte[] b, int s, int l, PrintStream ps) -> {
-        StringBuilder buf = new StringBuilder(AUUID.UUID_CHARS + 2);
-        buf.append('"');
-        AUUID.appendLiteralOnly(b, s + 1, buf).append('"');
-        ps.print(buf.toString());
+    public static final IPrinter PRINTER = new ATaggedValuePrinter() {
+        @Override
+        protected void printNonTaggedValue(byte[] b, int s, int l, java.io.PrintStream ps) {
+            ps.print(ADateTimeSerializerDeserializer.getChronon(b, s + 1));
+        }
     };
 
     @Override
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/ADayTimeDurationPrinterFactory.java
similarity index 67%
copy from asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java
copy to asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/ADayTimeDurationPrinterFactory.java
index f1c853f..b660afa 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/ADayTimeDurationPrinterFactory.java
@@ -16,26 +16,25 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-
-package org.apache.asterix.dataflow.data.nontagged.printers.json.clean;
+package org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm;
 
 import java.io.PrintStream;
 
-import org.apache.asterix.om.base.AUUID;
+import org.apache.asterix.dataflow.data.nontagged.serde.ADayTimeDurationSerializerDeserializer;
 import org.apache.hyracks.algebricks.data.IPrinter;
 import org.apache.hyracks.algebricks.data.IPrinterFactory;
 
-public class AUUIDPrinterFactory implements IPrinterFactory {
+public class ADayTimeDurationPrinterFactory implements IPrinterFactory {
 
     private static final long serialVersionUID = 1L;
 
-    public static final AUUIDPrinterFactory INSTANCE = new AUUIDPrinterFactory();
+    public static final ADayTimeDurationPrinterFactory INSTANCE = new ADayTimeDurationPrinterFactory();
 
-    public static final IPrinter PRINTER = (byte[] b, int s, int l, PrintStream ps) -> {
-        StringBuilder buf = new StringBuilder(AUUID.UUID_CHARS + 2);
-        buf.append('"');
-        AUUID.appendLiteralOnly(b, s + 1, buf).append('"');
-        ps.print(buf.toString());
+    public static final IPrinter PRINTER = new ATaggedValuePrinter() {
+        @Override
+        protected void printNonTaggedValue(byte[] b, int s, int l, PrintStream ps) {
+            ps.print(ADayTimeDurationSerializerDeserializer.getDayTime(b, s + 1));
+        }
     };
 
     @Override
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/ADoublePrinterFactory.java
similarity index 69%
copy from asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java
copy to asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/ADoublePrinterFactory.java
index f1c853f..af851b1 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/ADoublePrinterFactory.java
@@ -16,27 +16,23 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+package org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm;
 
-package org.apache.asterix.dataflow.data.nontagged.printers.json.clean;
+import java.io.IOException;
 
-import java.io.PrintStream;
-
-import org.apache.asterix.om.base.AUUID;
 import org.apache.hyracks.algebricks.data.IPrinter;
 import org.apache.hyracks.algebricks.data.IPrinterFactory;
 
-public class AUUIDPrinterFactory implements IPrinterFactory {
-
-    private static final long serialVersionUID = 1L;
+public class ADoublePrinterFactory implements IPrinterFactory {
 
-    public static final AUUIDPrinterFactory INSTANCE = new AUUIDPrinterFactory();
-
-    public static final IPrinter PRINTER = (byte[] b, int s, int l, PrintStream ps) -> {
-        StringBuilder buf = new StringBuilder(AUUID.UUID_CHARS + 2);
-        buf.append('"');
-        AUUID.appendLiteralOnly(b, s + 1, buf).append('"');
-        ps.print(buf.toString());
+    public static final ADoublePrinterFactory INSTANCE = new ADoublePrinterFactory();
+    public static final IPrinter PRINTER = new ATaggedValuePrinter() {
+        @Override
+        protected void printNonTaggedValue(byte[] b, int s, int l, java.io.PrintStream ps) throws IOException {
+            printDouble(b, s + 1, ps);
+        }
     };
+    private static final long serialVersionUID = 1L;
 
     @Override
     public IPrinter createPrinter() {
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/ADurationPrinterFactory.java
similarity index 61%
copy from asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java
copy to asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/ADurationPrinterFactory.java
index f1c853f..838d431 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/ADurationPrinterFactory.java
@@ -16,26 +16,27 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+package org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm;
 
-package org.apache.asterix.dataflow.data.nontagged.printers.json.clean;
-
-import java.io.PrintStream;
-
-import org.apache.asterix.om.base.AUUID;
+import org.apache.asterix.dataflow.data.nontagged.serde.ADurationSerializerDeserializer;
 import org.apache.hyracks.algebricks.data.IPrinter;
 import org.apache.hyracks.algebricks.data.IPrinterFactory;
 
-public class AUUIDPrinterFactory implements IPrinterFactory {
+public class ADurationPrinterFactory implements IPrinterFactory {
 
     private static final long serialVersionUID = 1L;
 
-    public static final AUUIDPrinterFactory INSTANCE = new AUUIDPrinterFactory();
-
-    public static final IPrinter PRINTER = (byte[] b, int s, int l, PrintStream ps) -> {
-        StringBuilder buf = new StringBuilder(AUUID.UUID_CHARS + 2);
-        buf.append('"');
-        AUUID.appendLiteralOnly(b, s + 1, buf).append('"');
-        ps.print(buf.toString());
+    public static final ADurationPrinterFactory INSTANCE = new ADurationPrinterFactory();
+
+    public static final IPrinter PRINTER = new ATaggedValuePrinter() {
+        @Override
+        protected void printNonTaggedValue(byte[] b, int s, int l, java.io.PrintStream ps) {
+            int yearMonth = ADurationSerializerDeserializer.getYearMonth(b, s + 1);
+            long dayTime = ADurationSerializerDeserializer.getDayTime(b, s + 1);
+            ps.print(yearMonth);
+            printDelimiter(ps);
+            ps.print(dayTime);
+        }
     };
 
     @Override
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/AFloatPrinterFactory.java
similarity index 69%
copy from asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java
copy to asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/AFloatPrinterFactory.java
index f1c853f..5121830 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/AFloatPrinterFactory.java
@@ -16,27 +16,21 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+package org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm;
 
-package org.apache.asterix.dataflow.data.nontagged.printers.json.clean;
-
-import java.io.PrintStream;
-
-import org.apache.asterix.om.base.AUUID;
 import org.apache.hyracks.algebricks.data.IPrinter;
 import org.apache.hyracks.algebricks.data.IPrinterFactory;
 
-public class AUUIDPrinterFactory implements IPrinterFactory {
-
-    private static final long serialVersionUID = 1L;
-
-    public static final AUUIDPrinterFactory INSTANCE = new AUUIDPrinterFactory();
+public class AFloatPrinterFactory implements IPrinterFactory {
 
-    public static final IPrinter PRINTER = (byte[] b, int s, int l, PrintStream ps) -> {
-        StringBuilder buf = new StringBuilder(AUUID.UUID_CHARS + 2);
-        buf.append('"');
-        AUUID.appendLiteralOnly(b, s + 1, buf).append('"');
-        ps.print(buf.toString());
+    public static final AFloatPrinterFactory INSTANCE = new AFloatPrinterFactory();
+    public static final IPrinter PRINTER = new ATaggedValuePrinter() {
+        @Override
+        protected void printNonTaggedValue(byte[] b, int s, int l, java.io.PrintStream ps) {
+            printFloat(b, s + 1, ps);
+        }
     };
+    private static final long serialVersionUID = 1L;
 
     @Override
     public IPrinter createPrinter() {
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/AInt16PrinterFactory.java
similarity index 68%
copy from asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java
copy to asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/AInt16PrinterFactory.java
index f1c853f..34884ec 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/AInt16PrinterFactory.java
@@ -16,26 +16,23 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+package org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm;
 
-package org.apache.asterix.dataflow.data.nontagged.printers.json.clean;
-
-import java.io.PrintStream;
-
-import org.apache.asterix.om.base.AUUID;
+import org.apache.asterix.dataflow.data.nontagged.serde.AInt16SerializerDeserializer;
 import org.apache.hyracks.algebricks.data.IPrinter;
 import org.apache.hyracks.algebricks.data.IPrinterFactory;
 
-public class AUUIDPrinterFactory implements IPrinterFactory {
+public class AInt16PrinterFactory implements IPrinterFactory {
 
     private static final long serialVersionUID = 1L;
 
-    public static final AUUIDPrinterFactory INSTANCE = new AUUIDPrinterFactory();
+    public static final AInt16PrinterFactory INSTANCE = new AInt16PrinterFactory();
 
-    public static final IPrinter PRINTER = (byte[] b, int s, int l, PrintStream ps) -> {
-        StringBuilder buf = new StringBuilder(AUUID.UUID_CHARS + 2);
-        buf.append('"');
-        AUUID.appendLiteralOnly(b, s + 1, buf).append('"');
-        ps.print(buf.toString());
+    public static final IPrinter PRINTER = new ATaggedValuePrinter() {
+        @Override
+        protected void printNonTaggedValue(byte[] b, int s, int l, java.io.PrintStream ps) {
+            ps.print(AInt16SerializerDeserializer.getShort(b, s + 1));
+        }
     };
 
     @Override
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/AInt32PrinterFactory.java
similarity index 69%
copy from asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java
copy to asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/AInt32PrinterFactory.java
index f1c853f..84986ba 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/AInt32PrinterFactory.java
@@ -16,26 +16,23 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+package org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm;
 
-package org.apache.asterix.dataflow.data.nontagged.printers.json.clean;
-
-import java.io.PrintStream;
-
-import org.apache.asterix.om.base.AUUID;
+import org.apache.asterix.dataflow.data.nontagged.serde.AInt32SerializerDeserializer;
 import org.apache.hyracks.algebricks.data.IPrinter;
 import org.apache.hyracks.algebricks.data.IPrinterFactory;
 
-public class AUUIDPrinterFactory implements IPrinterFactory {
+public class AInt32PrinterFactory implements IPrinterFactory {
 
     private static final long serialVersionUID = 1L;
 
-    public static final AUUIDPrinterFactory INSTANCE = new AUUIDPrinterFactory();
+    public static final AInt32PrinterFactory INSTANCE = new AInt32PrinterFactory();
 
-    public static final IPrinter PRINTER = (byte[] b, int s, int l, PrintStream ps) -> {
-        StringBuilder buf = new StringBuilder(AUUID.UUID_CHARS + 2);
-        buf.append('"');
-        AUUID.appendLiteralOnly(b, s + 1, buf).append('"');
-        ps.print(buf.toString());
+    public static final IPrinter PRINTER = new ATaggedValuePrinter() {
+        @Override
+        protected void printNonTaggedValue(byte[] b, int s, int l, java.io.PrintStream ps) {
+            ps.print(AInt32SerializerDeserializer.getInt(b, s + 1));
+        }
     };
 
     @Override
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/AInt64PrinterFactory.java
similarity index 76%
copy from asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java
copy to asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/AInt64PrinterFactory.java
index f1c853f..2a067fd 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/AInt64PrinterFactory.java
@@ -16,26 +16,25 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-
-package org.apache.asterix.dataflow.data.nontagged.printers.json.clean;
+package org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm;
 
 import java.io.PrintStream;
 
-import org.apache.asterix.om.base.AUUID;
+import org.apache.asterix.dataflow.data.nontagged.serde.AInt64SerializerDeserializer;
 import org.apache.hyracks.algebricks.data.IPrinter;
 import org.apache.hyracks.algebricks.data.IPrinterFactory;
 
-public class AUUIDPrinterFactory implements IPrinterFactory {
+/**
+ * Int64 value is printed as JSON number.
+ */
+public class AInt64PrinterFactory implements IPrinterFactory {
 
     private static final long serialVersionUID = 1L;
 
-    public static final AUUIDPrinterFactory INSTANCE = new AUUIDPrinterFactory();
+    public static final AInt64PrinterFactory INSTANCE = new AInt64PrinterFactory();
 
     public static final IPrinter PRINTER = (byte[] b, int s, int l, PrintStream ps) -> {
-        StringBuilder buf = new StringBuilder(AUUID.UUID_CHARS + 2);
-        buf.append('"');
-        AUUID.appendLiteralOnly(b, s + 1, buf).append('"');
-        ps.print(buf.toString());
+        ps.print(AInt64SerializerDeserializer.getLong(b, s + 1));
     };
 
     @Override
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/AInt8PrinterFactory.java
similarity index 70%
copy from asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java
copy to asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/AInt8PrinterFactory.java
index f1c853f..dcfac5e 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/AInt8PrinterFactory.java
@@ -16,26 +16,23 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+package org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm;
 
-package org.apache.asterix.dataflow.data.nontagged.printers.json.clean;
-
-import java.io.PrintStream;
-
-import org.apache.asterix.om.base.AUUID;
+import org.apache.asterix.dataflow.data.nontagged.serde.AInt8SerializerDeserializer;
 import org.apache.hyracks.algebricks.data.IPrinter;
 import org.apache.hyracks.algebricks.data.IPrinterFactory;
 
-public class AUUIDPrinterFactory implements IPrinterFactory {
+public class AInt8PrinterFactory implements IPrinterFactory {
 
     private static final long serialVersionUID = 1L;
 
-    public static final AUUIDPrinterFactory INSTANCE = new AUUIDPrinterFactory();
+    public static final AInt8PrinterFactory INSTANCE = new AInt8PrinterFactory();
 
-    public static final IPrinter PRINTER = (byte[] b, int s, int l, PrintStream ps) -> {
-        StringBuilder buf = new StringBuilder(AUUID.UUID_CHARS + 2);
-        buf.append('"');
-        AUUID.appendLiteralOnly(b, s + 1, buf).append('"');
-        ps.print(buf.toString());
+    public static final IPrinter PRINTER = new ATaggedValuePrinter() {
+        @Override
+        protected void printNonTaggedValue(byte[] b, int s, int l, java.io.PrintStream ps) {
+            ps.print(AInt8SerializerDeserializer.getByte(b, s + 1));
+        }
     };
 
     @Override
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/ALinePrinterFactory.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/ALinePrinterFactory.java
new file mode 100644
index 0000000..4669922
--- /dev/null
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/ALinePrinterFactory.java
@@ -0,0 +1,56 @@
+/*
+ * 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.asterix.dataflow.data.nontagged.printers.json.losslessadm;
+
+import java.io.IOException;
+
+import org.apache.asterix.dataflow.data.nontagged.Coordinate;
+import org.apache.asterix.dataflow.data.nontagged.serde.ALineSerializerDeserializer;
+import org.apache.hyracks.algebricks.data.IPrinter;
+import org.apache.hyracks.algebricks.data.IPrinterFactory;
+
+public class ALinePrinterFactory implements IPrinterFactory {
+
+    private static final long serialVersionUID = 1L;
+
+    public static final ALinePrinterFactory INSTANCE = new ALinePrinterFactory();
+
+    public static final IPrinter PRINTER = new ATaggedValuePrinter() {
+        @Override
+        protected void printNonTaggedValue(byte[] b, int s, int l, java.io.PrintStream ps) throws IOException {
+            int offsetX1 = ALineSerializerDeserializer.getStartPointCoordinateOffset(Coordinate.X);
+            int offsetY1 = ALineSerializerDeserializer.getStartPointCoordinateOffset(Coordinate.Y);
+            int offsetX2 = ALineSerializerDeserializer.getEndPointCoordinateOffset(Coordinate.X);
+            int offsetY2 = ALineSerializerDeserializer.getEndPointCoordinateOffset(Coordinate.Y);
+            printDouble(b, s + 1 + offsetX1, ps);
+            printDelimiter(ps);
+            printDouble(b, s + 1 + offsetY1, ps);
+            printDelimiter(ps);
+            printDouble(b, s + 1 + offsetX2, ps);
+            printDelimiter(ps);
+            printDouble(b, s + 1 + offsetY2, ps);
+        }
+    };
+
+    @Override
+    public IPrinter createPrinter() {
+        return PRINTER;
+    }
+}
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/AMissingPrinterFactory.java
similarity index 65%
copy from asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java
copy to asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/AMissingPrinterFactory.java
index f1c853f..3018d6a 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/AMissingPrinterFactory.java
@@ -17,29 +17,35 @@
  * under the License.
  */
 
-package org.apache.asterix.dataflow.data.nontagged.printers.json.clean;
+package org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm;
 
-import java.io.PrintStream;
+import java.io.IOException;
 
-import org.apache.asterix.om.base.AUUID;
 import org.apache.hyracks.algebricks.data.IPrinter;
 import org.apache.hyracks.algebricks.data.IPrinterFactory;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
 
-public class AUUIDPrinterFactory implements IPrinterFactory {
+/**
+ * Missing value is printed as standalone type code.
+ */
+public class AMissingPrinterFactory implements IPrinterFactory {
 
     private static final long serialVersionUID = 1L;
 
-    public static final AUUIDPrinterFactory INSTANCE = new AUUIDPrinterFactory();
+    public static final AMissingPrinterFactory INSTANCE = new AMissingPrinterFactory();
 
-    public static final IPrinter PRINTER = (byte[] b, int s, int l, PrintStream ps) -> {
-        StringBuilder buf = new StringBuilder(AUUID.UUID_CHARS + 2);
-        buf.append('"');
-        AUUID.appendLiteralOnly(b, s + 1, buf).append('"');
-        ps.print(buf.toString());
+    public static final IPrinter PRINTER = (b, s, l, ps) -> {
+        try {
+            ps.print('"');
+            ATaggedValuePrinter.printTypeTag(b, s, ps);
+            ps.print('"');
+        } catch (IOException e) {
+            throw HyracksDataException.create(e);
+        }
     };
 
     @Override
     public IPrinter createPrinter() {
         return PRINTER;
     }
-}
+}
\ No newline at end of file
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/ANullPrinterFactory.java
similarity index 75%
copy from asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java
copy to asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/ANullPrinterFactory.java
index f1c853f..9dad25d 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/ANullPrinterFactory.java
@@ -16,27 +16,23 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-
-package org.apache.asterix.dataflow.data.nontagged.printers.json.clean;
+package org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm;
 
 import java.io.PrintStream;
 
-import org.apache.asterix.om.base.AUUID;
 import org.apache.hyracks.algebricks.data.IPrinter;
 import org.apache.hyracks.algebricks.data.IPrinterFactory;
 
-public class AUUIDPrinterFactory implements IPrinterFactory {
+/**
+ * Null value is printed as JSON null.
+ */
+public class ANullPrinterFactory implements IPrinterFactory {
 
     private static final long serialVersionUID = 1L;
 
-    public static final AUUIDPrinterFactory INSTANCE = new AUUIDPrinterFactory();
+    public static final ANullPrinterFactory INSTANCE = new ANullPrinterFactory();
 
-    public static final IPrinter PRINTER = (byte[] b, int s, int l, PrintStream ps) -> {
-        StringBuilder buf = new StringBuilder(AUUID.UUID_CHARS + 2);
-        buf.append('"');
-        AUUID.appendLiteralOnly(b, s + 1, buf).append('"');
-        ps.print(buf.toString());
-    };
+    public static final IPrinter PRINTER = (byte[] b, int s, int l, PrintStream ps) -> ps.print("null");
 
     @Override
     public IPrinter createPrinter() {
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/AObjectPrinterFactory.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/AObjectPrinterFactory.java
new file mode 100644
index 0000000..01c3da0
--- /dev/null
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/AObjectPrinterFactory.java
@@ -0,0 +1,161 @@
+/*
+ * 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.asterix.dataflow.data.nontagged.printers.json.losslessadm;
+
+import java.io.PrintStream;
+
+import org.apache.asterix.om.pointables.AListVisitablePointable;
+import org.apache.asterix.om.pointables.ARecordVisitablePointable;
+import org.apache.asterix.om.pointables.base.DefaultOpenFieldType;
+import org.apache.asterix.om.pointables.printer.IPrintVisitor;
+import org.apache.asterix.om.pointables.printer.json.losslessadm.APrintVisitor;
+import org.apache.asterix.om.types.ATypeTag;
+import org.apache.asterix.om.types.EnumDeserializer;
+import org.apache.hyracks.algebricks.common.utils.Pair;
+import org.apache.hyracks.algebricks.data.IPrinter;
+import org.apache.hyracks.algebricks.data.IPrinterFactory;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+
+public final class AObjectPrinterFactory implements IPrinterFactory {
+
+    private static final long serialVersionUID = 1L;
+
+    public static final AObjectPrinterFactory INSTANCE = new AObjectPrinterFactory();
+
+    public static boolean printFlatValue(ATypeTag typeTag, byte[] b, int s, int l, PrintStream ps)
+            throws HyracksDataException {
+        switch (typeTag) {
+            case TINYINT:
+                AInt8PrinterFactory.PRINTER.print(b, s, l, ps);
+                return true;
+            case SMALLINT:
+                AInt16PrinterFactory.PRINTER.print(b, s, l, ps);
+                return true;
+            case INTEGER:
+                AInt32PrinterFactory.PRINTER.print(b, s, l, ps);
+                return true;
+            case BIGINT:
+                AInt64PrinterFactory.PRINTER.print(b, s, l, ps);
+                return true;
+            case MISSING:
+                AMissingPrinterFactory.PRINTER.print(b, s, l, ps);
+                return true;
+            case NULL:
+                ANullPrinterFactory.PRINTER.print(b, s, l, ps);
+                return true;
+            case BOOLEAN:
+                ABooleanPrinterFactory.PRINTER.print(b, s, l, ps);
+                return true;
+            case FLOAT:
+                AFloatPrinterFactory.PRINTER.print(b, s, l, ps);
+                return true;
+            case DOUBLE:
+                ADoublePrinterFactory.PRINTER.print(b, s, l, ps);
+                return true;
+            case DATE:
+                ADatePrinterFactory.PRINTER.print(b, s, l, ps);
+                return true;
+            case TIME:
+                ATimePrinterFactory.PRINTER.print(b, s, l, ps);
+                return true;
+            case DATETIME:
+                ADateTimePrinterFactory.PRINTER.print(b, s, l, ps);
+                return true;
+            case DURATION:
+                ADurationPrinterFactory.PRINTER.print(b, s, l, ps);
+                return true;
+            case YEARMONTHDURATION:
+                AYearMonthDurationPrinterFactory.PRINTER.print(b, s, l, ps);
+                return true;
+            case DAYTIMEDURATION:
+                ADayTimeDurationPrinterFactory.PRINTER.print(b, s, l, ps);
+                return true;
+            case STRING:
+                AStringPrinterFactory.PRINTER.print(b, s, l, ps);
+                return true;
+            case BINARY:
+                ABinaryPrinterFactory.PRINTER.print(b, s, l, ps);
+                return true;
+            case UUID:
+                AUUIDPrinterFactory.PRINTER.print(b, s, l, ps);
+                return true;
+            case POINT:
+                APointPrinterFactory.PRINTER.print(b, s, l, ps);
+                return true;
+            case POINT3D:
+                APoint3DPrinterFactory.PRINTER.print(b, s, l, ps);
+                return true;
+            case CIRCLE:
+                ACirclePrinterFactory.PRINTER.print(b, s, l, ps);
+                return true;
+            case LINE:
+                ALinePrinterFactory.PRINTER.print(b, s, l, ps);
+                return true;
+            case RECTANGLE:
+                ARectanglePrinterFactory.PRINTER.print(b, s, l, ps);
+                return true;
+            case POLYGON:
+                APolygonPrinterFactory.PRINTER.print(b, s, l, ps);
+                return true;
+            case INTERVAL:
+            case GEOMETRY:
+                // NYI
+            default:
+                return false;
+        }
+    }
+
+    @Override
+    public IPrinter createPrinter() {
+        final ARecordVisitablePointable rPointable =
+                new ARecordVisitablePointable(DefaultOpenFieldType.NESTED_OPEN_RECORD_TYPE);
+        final AListVisitablePointable olPointable =
+                new AListVisitablePointable(DefaultOpenFieldType.NESTED_OPEN_AORDERED_LIST_TYPE);
+        final AListVisitablePointable ulPointable =
+                new AListVisitablePointable(DefaultOpenFieldType.NESTED_OPEN_AUNORDERED_LIST_TYPE);
+        final Pair<PrintStream, ATypeTag> streamTag = new Pair<>(null, null);
+
+        final IPrintVisitor visitor = new APrintVisitor();
+
+        return (byte[] b, int s, int l, PrintStream ps) -> {
+            ATypeTag typeTag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(b[s]);
+            if (!printFlatValue(typeTag, b, s, l, ps)) {
+                streamTag.first = ps;
+                streamTag.second = typeTag;
+                switch (typeTag) {
+                    case OBJECT:
+                        rPointable.set(b, s, l);
+                        visitor.visit(rPointable, streamTag);
+                        break;
+                    case ARRAY:
+                        olPointable.set(b, s, l);
+                        visitor.visit(olPointable, streamTag);
+                        break;
+                    case MULTISET:
+                        ulPointable.set(b, s, l);
+                        visitor.visit(ulPointable, streamTag);
+                        break;
+                    default:
+                        throw new HyracksDataException("No printer for type " + typeTag);
+                }
+            }
+        };
+    }
+}
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/AOptionalFieldPrinterFactory.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/AOptionalFieldPrinterFactory.java
new file mode 100644
index 0000000..25c77070
--- /dev/null
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/AOptionalFieldPrinterFactory.java
@@ -0,0 +1,73 @@
+/*
+ * 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.asterix.dataflow.data.nontagged.printers.json.losslessadm;
+
+import java.io.PrintStream;
+
+import org.apache.asterix.formats.nontagged.LosslessADMJSONPrinterFactoryProvider;
+import org.apache.asterix.om.types.ATypeTag;
+import org.apache.asterix.om.types.AUnionType;
+import org.apache.asterix.om.types.BuiltinType;
+import org.apache.hyracks.algebricks.data.IPrinter;
+import org.apache.hyracks.algebricks.data.IPrinterFactory;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+
+public class AOptionalFieldPrinterFactory implements IPrinterFactory {
+
+    private static final long serialVersionUID = 1L;
+    private final AUnionType unionType;
+
+    public AOptionalFieldPrinterFactory(AUnionType unionType) {
+        this.unionType = unionType;
+    }
+
+    @Override
+    public IPrinter createPrinter() {
+        return new IPrinter() {
+            private IPrinter missingPrinter;
+            private IPrinter nullPrinter;
+            private IPrinter fieldPrinter;
+
+            @Override
+            public void init() throws HyracksDataException {
+                missingPrinter =
+                        (LosslessADMJSONPrinterFactoryProvider.INSTANCE.getPrinterFactory(BuiltinType.AMISSING))
+                                .createPrinter();
+                nullPrinter = (LosslessADMJSONPrinterFactoryProvider.INSTANCE.getPrinterFactory(BuiltinType.ANULL))
+                        .createPrinter();
+                fieldPrinter =
+                        (LosslessADMJSONPrinterFactoryProvider.INSTANCE.getPrinterFactory(unionType.getActualType()))
+                                .createPrinter();
+            }
+
+            @Override
+            public void print(byte[] b, int s, int l, PrintStream ps) throws HyracksDataException {
+                fieldPrinter.init();
+                if (b[s] == ATypeTag.SERIALIZED_MISSING_TYPE_TAG) {
+                    missingPrinter.print(b, s, l, ps);
+                } else if (b[s] == ATypeTag.SERIALIZED_NULL_TYPE_TAG) {
+                    nullPrinter.print(b, s, l, ps);
+                } else {
+                    fieldPrinter.print(b, s, l, ps);
+                }
+            }
+        };
+    }
+}
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/AOrderedlistPrinterFactory.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/AOrderedlistPrinterFactory.java
new file mode 100644
index 0000000..58988f7
--- /dev/null
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/AOrderedlistPrinterFactory.java
@@ -0,0 +1,68 @@
+/*
+ * 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.asterix.dataflow.data.nontagged.printers.json.losslessadm;
+
+import java.io.PrintStream;
+
+import org.apache.asterix.om.pointables.PointableAllocator;
+import org.apache.asterix.om.pointables.base.DefaultOpenFieldType;
+import org.apache.asterix.om.pointables.base.IVisitablePointable;
+import org.apache.asterix.om.pointables.printer.json.losslessadm.APrintVisitor;
+import org.apache.asterix.om.types.AOrderedListType;
+import org.apache.asterix.om.types.ATypeTag;
+import org.apache.asterix.om.types.IAType;
+import org.apache.hyracks.algebricks.common.utils.Pair;
+import org.apache.hyracks.algebricks.data.IPrinter;
+import org.apache.hyracks.algebricks.data.IPrinterFactory;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+
+public class AOrderedlistPrinterFactory implements IPrinterFactory {
+
+    private static final long serialVersionUID = 1L;
+    private final AOrderedListType orderedlistType;
+
+    public AOrderedlistPrinterFactory(AOrderedListType orderedlistType) {
+        this.orderedlistType = orderedlistType;
+    }
+
+    @Override
+    public IPrinter createPrinter() {
+        final PointableAllocator allocator = new PointableAllocator();
+        final IAType inputType = orderedlistType == null ? DefaultOpenFieldType.getDefaultOpenFieldType(ATypeTag.ARRAY)
+                : orderedlistType;
+        final IVisitablePointable listAccessor = allocator.allocateListValue(inputType);
+        final APrintVisitor printVisitor = new APrintVisitor();
+        final Pair<PrintStream, ATypeTag> arg = new Pair<>(null, null);
+
+        return new IPrinter() {
+            @Override
+            public void init() {
+                arg.second = inputType.getTypeTag();
+            }
+
+            @Override
+            public void print(byte[] b, int start, int l, PrintStream ps) throws HyracksDataException {
+                listAccessor.set(b, start, l);
+                arg.first = ps;
+                listAccessor.accept(printVisitor, arg);
+            }
+        };
+    }
+}
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/APoint3DPrinterFactory.java
similarity index 52%
copy from asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java
copy to asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/APoint3DPrinterFactory.java
index f1c853f..8367bdb 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/APoint3DPrinterFactory.java
@@ -17,25 +17,33 @@
  * under the License.
  */
 
-package org.apache.asterix.dataflow.data.nontagged.printers.json.clean;
+package org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm;
 
-import java.io.PrintStream;
+import java.io.IOException;
 
-import org.apache.asterix.om.base.AUUID;
+import org.apache.asterix.dataflow.data.nontagged.Coordinate;
+import org.apache.asterix.dataflow.data.nontagged.serde.APoint3DSerializerDeserializer;
 import org.apache.hyracks.algebricks.data.IPrinter;
 import org.apache.hyracks.algebricks.data.IPrinterFactory;
 
-public class AUUIDPrinterFactory implements IPrinterFactory {
+public class APoint3DPrinterFactory implements IPrinterFactory {
 
     private static final long serialVersionUID = 1L;
 
-    public static final AUUIDPrinterFactory INSTANCE = new AUUIDPrinterFactory();
-
-    public static final IPrinter PRINTER = (byte[] b, int s, int l, PrintStream ps) -> {
-        StringBuilder buf = new StringBuilder(AUUID.UUID_CHARS + 2);
-        buf.append('"');
-        AUUID.appendLiteralOnly(b, s + 1, buf).append('"');
-        ps.print(buf.toString());
+    public static final APoint3DPrinterFactory INSTANCE = new APoint3DPrinterFactory();
+
+    public static final IPrinter PRINTER = new ATaggedValuePrinter() {
+        @Override
+        protected void printNonTaggedValue(byte[] b, int s, int l, java.io.PrintStream ps) throws IOException {
+            int offsetX = APoint3DSerializerDeserializer.getCoordinateOffset(Coordinate.X);
+            int offsetY = APoint3DSerializerDeserializer.getCoordinateOffset(Coordinate.Y);
+            int offsetZ = APoint3DSerializerDeserializer.getCoordinateOffset(Coordinate.Z);
+            printDouble(b, s + 1 + offsetX, ps);
+            printDelimiter(ps);
+            printDouble(b, s + 1 + offsetY, ps);
+            printDelimiter(ps);
+            printDouble(b, s + 1 + offsetZ, ps);
+        }
     };
 
     @Override
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/APointPrinterFactory.java
similarity index 56%
copy from asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java
copy to asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/APointPrinterFactory.java
index f1c853f..c6fa6f5 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/APointPrinterFactory.java
@@ -17,25 +17,30 @@
  * under the License.
  */
 
-package org.apache.asterix.dataflow.data.nontagged.printers.json.clean;
+package org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm;
 
-import java.io.PrintStream;
+import java.io.IOException;
 
-import org.apache.asterix.om.base.AUUID;
+import org.apache.asterix.dataflow.data.nontagged.Coordinate;
+import org.apache.asterix.dataflow.data.nontagged.serde.APointSerializerDeserializer;
 import org.apache.hyracks.algebricks.data.IPrinter;
 import org.apache.hyracks.algebricks.data.IPrinterFactory;
 
-public class AUUIDPrinterFactory implements IPrinterFactory {
+public class APointPrinterFactory implements IPrinterFactory {
 
     private static final long serialVersionUID = 1L;
 
-    public static final AUUIDPrinterFactory INSTANCE = new AUUIDPrinterFactory();
-
-    public static final IPrinter PRINTER = (byte[] b, int s, int l, PrintStream ps) -> {
-        StringBuilder buf = new StringBuilder(AUUID.UUID_CHARS + 2);
-        buf.append('"');
-        AUUID.appendLiteralOnly(b, s + 1, buf).append('"');
-        ps.print(buf.toString());
+    public static final APointPrinterFactory INSTANCE = new APointPrinterFactory();
+
+    public static final IPrinter PRINTER = new ATaggedValuePrinter() {
+        @Override
+        protected void printNonTaggedValue(byte[] b, int s, int l, java.io.PrintStream ps) throws IOException {
+            int offsetX = APointSerializerDeserializer.getCoordinateOffset(Coordinate.X);
+            int offsetY = APointSerializerDeserializer.getCoordinateOffset(Coordinate.Y);
+            printDouble(b, s + 1 + offsetX, ps);
+            printDelimiter(ps);
+            printDouble(b, s + 1 + offsetY, ps);
+        }
     };
 
     @Override
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/APolygonPrinterFactory.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/APolygonPrinterFactory.java
new file mode 100644
index 0000000..ad18b61
--- /dev/null
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/APolygonPrinterFactory.java
@@ -0,0 +1,57 @@
+/*
+ * 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.asterix.dataflow.data.nontagged.printers.json.losslessadm;
+
+import java.io.IOException;
+
+import org.apache.asterix.dataflow.data.nontagged.Coordinate;
+import org.apache.asterix.dataflow.data.nontagged.serde.AInt16SerializerDeserializer;
+import org.apache.asterix.dataflow.data.nontagged.serde.APolygonSerializerDeserializer;
+import org.apache.hyracks.algebricks.data.IPrinter;
+import org.apache.hyracks.algebricks.data.IPrinterFactory;
+
+public class APolygonPrinterFactory implements IPrinterFactory {
+
+    private static final long serialVersionUID = 1L;
+
+    public static final APolygonPrinterFactory INSTANCE = new APolygonPrinterFactory();
+
+    public static final IPrinter PRINTER = new ATaggedValuePrinter() {
+        @Override
+        protected void printNonTaggedValue(byte[] b, int s, int l, java.io.PrintStream ps) throws IOException {
+            int numOfPoints = AInt16SerializerDeserializer.getShort(b,
+                    s + 1 + APolygonSerializerDeserializer.getNumberOfPointsOffset());
+            ps.print(numOfPoints);
+            for (int i = 0; i < numOfPoints; i++) {
+                int offsetX = APolygonSerializerDeserializer.getCoordinateOffset(i, Coordinate.X);
+                int offsetY = APolygonSerializerDeserializer.getCoordinateOffset(i, Coordinate.Y);
+                printDelimiter(ps);
+                printDouble(b, s + 1 + offsetX, ps);
+                printDelimiter(ps);
+                printDouble(b, s + 1 + offsetY, ps);
+            }
+        }
+    };
+
+    @Override
+    public IPrinter createPrinter() {
+        return PRINTER;
+    }
+}
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/ARecordPrinterFactory.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/ARecordPrinterFactory.java
new file mode 100644
index 0000000..9c715a9
--- /dev/null
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/ARecordPrinterFactory.java
@@ -0,0 +1,68 @@
+/*
+ * 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.asterix.dataflow.data.nontagged.printers.json.losslessadm;
+
+import java.io.PrintStream;
+
+import org.apache.asterix.om.pointables.PointableAllocator;
+import org.apache.asterix.om.pointables.base.DefaultOpenFieldType;
+import org.apache.asterix.om.pointables.base.IVisitablePointable;
+import org.apache.asterix.om.pointables.printer.json.losslessadm.APrintVisitor;
+import org.apache.asterix.om.types.ARecordType;
+import org.apache.asterix.om.types.ATypeTag;
+import org.apache.asterix.om.types.IAType;
+import org.apache.hyracks.algebricks.common.utils.Pair;
+import org.apache.hyracks.algebricks.data.IPrinter;
+import org.apache.hyracks.algebricks.data.IPrinterFactory;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+
+public class ARecordPrinterFactory implements IPrinterFactory {
+
+    private static final long serialVersionUID = 1L;
+    private final ARecordType recType;
+
+    public ARecordPrinterFactory(ARecordType recType) {
+        this.recType = recType;
+    }
+
+    @Override
+    public IPrinter createPrinter() {
+        final PointableAllocator allocator = new PointableAllocator();
+        final IAType inputType =
+                recType == null ? DefaultOpenFieldType.getDefaultOpenFieldType(ATypeTag.OBJECT) : recType;
+        final IVisitablePointable recAccessor = allocator.allocateRecordValue(inputType);
+        final APrintVisitor printVisitor = new APrintVisitor();
+        final Pair<PrintStream, ATypeTag> arg = new Pair<>(null, null);
+
+        return new IPrinter() {
+            @Override
+            public void init() {
+                arg.second = inputType.getTypeTag();
+            }
+
+            @Override
+            public void print(byte[] b, int start, int l, PrintStream ps) throws HyracksDataException {
+                recAccessor.set(b, start, l);
+                arg.first = ps;
+                recAccessor.accept(printVisitor, arg);
+            }
+        };
+    }
+}
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/ARectanglePrinterFactory.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/ARectanglePrinterFactory.java
new file mode 100644
index 0000000..59fa919
--- /dev/null
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/ARectanglePrinterFactory.java
@@ -0,0 +1,56 @@
+/*
+ * 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.asterix.dataflow.data.nontagged.printers.json.losslessadm;
+
+import java.io.IOException;
+
+import org.apache.asterix.dataflow.data.nontagged.Coordinate;
+import org.apache.asterix.dataflow.data.nontagged.serde.ARectangleSerializerDeserializer;
+import org.apache.hyracks.algebricks.data.IPrinter;
+import org.apache.hyracks.algebricks.data.IPrinterFactory;
+
+public class ARectanglePrinterFactory implements IPrinterFactory {
+
+    private static final long serialVersionUID = 1L;
+
+    public static final ARectanglePrinterFactory INSTANCE = new ARectanglePrinterFactory();
+
+    public static final IPrinter PRINTER = new ATaggedValuePrinter() {
+        @Override
+        protected void printNonTaggedValue(byte[] b, int s, int l, java.io.PrintStream ps) throws IOException {
+            int offsetX1 = ARectangleSerializerDeserializer.getBottomLeftCoordinateOffset(Coordinate.X);
+            int offsetY1 = ARectangleSerializerDeserializer.getBottomLeftCoordinateOffset(Coordinate.Y);
+            int offsetX2 = ARectangleSerializerDeserializer.getUpperRightCoordinateOffset(Coordinate.X);
+            int offsetY2 = ARectangleSerializerDeserializer.getUpperRightCoordinateOffset(Coordinate.Y);
+            printDouble(b, s + 1 + offsetX1, ps);
+            printDelimiter(ps);
+            printDouble(b, s + 1 + offsetY1, ps);
+            printDelimiter(ps);
+            printDouble(b, s + 1 + offsetX2, ps);
+            printDelimiter(ps);
+            printDouble(b, s + 1 + offsetY2, ps);
+        }
+    };
+
+    @Override
+    public IPrinter createPrinter() {
+        return PRINTER;
+    }
+}
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/AStringPrinterFactory.java
similarity index 54%
copy from asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java
copy to asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/AStringPrinterFactory.java
index f1c853f..c381336 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/AStringPrinterFactory.java
@@ -17,25 +17,39 @@
  * under the License.
  */
 
-package org.apache.asterix.dataflow.data.nontagged.printers.json.clean;
+package org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm;
 
-import java.io.PrintStream;
+import java.io.IOException;
 
-import org.apache.asterix.om.base.AUUID;
+import org.apache.asterix.dataflow.data.nontagged.printers.PrintTools;
 import org.apache.hyracks.algebricks.data.IPrinter;
 import org.apache.hyracks.algebricks.data.IPrinterFactory;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.apache.hyracks.util.string.UTF8StringUtil;
 
-public class AUUIDPrinterFactory implements IPrinterFactory {
+/*
+ * String value printed without type code.
+ * Empty string is printed as empty string.
+ */
+public class AStringPrinterFactory implements IPrinterFactory {
 
     private static final long serialVersionUID = 1L;
 
-    public static final AUUIDPrinterFactory INSTANCE = new AUUIDPrinterFactory();
-
-    public static final IPrinter PRINTER = (byte[] b, int s, int l, PrintStream ps) -> {
-        StringBuilder buf = new StringBuilder(AUUID.UUID_CHARS + 2);
-        buf.append('"');
-        AUUID.appendLiteralOnly(b, s + 1, buf).append('"');
-        ps.print(buf.toString());
+    public static final AStringPrinterFactory INSTANCE = new AStringPrinterFactory();
+
+    public static final IPrinter PRINTER = (b, s, l, ps) -> {
+        try {
+            int utfLength = UTF8StringUtil.getUTFLength(b, s + 1);
+            ps.print('"');
+            if (utfLength > 0) {
+                ATaggedValuePrinter.printDelimiter(ps);
+                PrintTools.writeUTF8StringAsJSONUnquoted(b, s + 1, l - 1, utfLength, ps);
+            }
+            ps.print('"');
+
+        } catch (IOException e) {
+            throw HyracksDataException.create(e);
+        }
     };
 
     @Override
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/ATaggedValuePrinter.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/ATaggedValuePrinter.java
new file mode 100644
index 0000000..62990b2
--- /dev/null
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/ATaggedValuePrinter.java
@@ -0,0 +1,67 @@
+/*
+ * 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.asterix.dataflow.data.nontagged.printers.json.losslessadm;
+
+import java.io.IOException;
+import java.io.PrintStream;
+
+import org.apache.asterix.dataflow.data.nontagged.serde.ADoubleSerializerDeserializer;
+import org.apache.asterix.dataflow.data.nontagged.serde.AFloatSerializerDeserializer;
+import org.apache.hyracks.algebricks.data.IPrinter;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.apache.hyracks.util.bytes.HexPrinter;
+
+public abstract class ATaggedValuePrinter implements IPrinter {
+
+    public static final char DELIMITER = ':';
+
+    @Override
+    public void print(byte[] b, int s, int l, PrintStream ps) throws HyracksDataException {
+        try {
+            ps.print("\"");
+            printTypeTag(b, s, ps);
+            printDelimiter(ps);
+            printNonTaggedValue(b, s, l, ps);
+            ps.print("\"");
+        } catch (IOException e) {
+            throw HyracksDataException.create(e);
+        }
+    }
+
+    static void printTypeTag(byte[] b, int s, PrintStream ps) throws IOException {
+        HexPrinter.printHexString(b, s, 1, ps);
+    }
+
+    static void printDelimiter(PrintStream ps) {
+        ps.print(DELIMITER);
+    }
+
+    static void printFloat(byte[] b, int s, PrintStream ps) {
+        int bits = AFloatSerializerDeserializer.getIntBits(b, s);
+        ps.print(bits);
+    }
+
+    static void printDouble(byte[] b, int s, PrintStream ps) {
+        long bits = ADoubleSerializerDeserializer.getLongBits(b, s);
+        ps.print(bits);
+    }
+
+    protected abstract void printNonTaggedValue(byte[] b, int s, int l, PrintStream ps) throws IOException;
+}
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/ATimePrinterFactory.java
similarity index 68%
copy from asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java
copy to asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/ATimePrinterFactory.java
index f1c853f..d0e551f 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/ATimePrinterFactory.java
@@ -16,26 +16,24 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+package org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm;
 
-package org.apache.asterix.dataflow.data.nontagged.printers.json.clean;
-
-import java.io.PrintStream;
-
-import org.apache.asterix.om.base.AUUID;
+import org.apache.asterix.dataflow.data.nontagged.serde.ATimeSerializerDeserializer;
 import org.apache.hyracks.algebricks.data.IPrinter;
 import org.apache.hyracks.algebricks.data.IPrinterFactory;
 
-public class AUUIDPrinterFactory implements IPrinterFactory {
+public class ATimePrinterFactory implements IPrinterFactory {
 
     private static final long serialVersionUID = 1L;
 
-    public static final AUUIDPrinterFactory INSTANCE = new AUUIDPrinterFactory();
+    public static final ATimePrinterFactory INSTANCE = new ATimePrinterFactory();
 
-    public static final IPrinter PRINTER = (byte[] b, int s, int l, PrintStream ps) -> {
-        StringBuilder buf = new StringBuilder(AUUID.UUID_CHARS + 2);
-        buf.append('"');
-        AUUID.appendLiteralOnly(b, s + 1, buf).append('"');
-        ps.print(buf.toString());
+    public static final IPrinter PRINTER = new ATaggedValuePrinter() {
+        @Override
+        protected void printNonTaggedValue(byte[] b, int s, int l, java.io.PrintStream ps) {
+            int chronon = ATimeSerializerDeserializer.getChronon(b, s + 1);
+            ps.print(chronon);
+        }
     };
 
     @Override
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/AUUIDPrinterFactory.java
similarity index 80%
copy from asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java
copy to asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/AUUIDPrinterFactory.java
index f1c853f..601d7fd 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/AUUIDPrinterFactory.java
@@ -17,9 +17,9 @@
  * under the License.
  */
 
-package org.apache.asterix.dataflow.data.nontagged.printers.json.clean;
+package org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm;
 
-import java.io.PrintStream;
+import java.io.IOException;
 
 import org.apache.asterix.om.base.AUUID;
 import org.apache.hyracks.algebricks.data.IPrinter;
@@ -31,11 +31,11 @@ public class AUUIDPrinterFactory implements IPrinterFactory {
 
     public static final AUUIDPrinterFactory INSTANCE = new AUUIDPrinterFactory();
 
-    public static final IPrinter PRINTER = (byte[] b, int s, int l, PrintStream ps) -> {
-        StringBuilder buf = new StringBuilder(AUUID.UUID_CHARS + 2);
-        buf.append('"');
-        AUUID.appendLiteralOnly(b, s + 1, buf).append('"');
-        ps.print(buf.toString());
+    public static final IPrinter PRINTER = new ATaggedValuePrinter() {
+        @Override
+        protected void printNonTaggedValue(byte[] b, int s, int l, java.io.PrintStream ps) throws IOException {
+            AUUID.appendLiteralOnly(b, s + 1, ps);
+        }
     };
 
     @Override
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/AUnionPrinterFactory.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/AUnionPrinterFactory.java
new file mode 100644
index 0000000..1f01326
--- /dev/null
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/AUnionPrinterFactory.java
@@ -0,0 +1,74 @@
+/*
+ * 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.asterix.dataflow.data.nontagged.printers.json.losslessadm;
+
+import java.io.PrintStream;
+import java.util.List;
+
+import org.apache.asterix.formats.nontagged.LosslessADMJSONPrinterFactoryProvider;
+import org.apache.asterix.om.types.ATypeTag;
+import org.apache.asterix.om.types.AUnionType;
+import org.apache.asterix.om.types.IAType;
+import org.apache.hyracks.algebricks.data.IPrinter;
+import org.apache.hyracks.algebricks.data.IPrinterFactory;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+
+public class AUnionPrinterFactory implements IPrinterFactory {
+
+    private static final long serialVersionUID = 1L;
+    private final AUnionType unionType;
+
+    public AUnionPrinterFactory(AUnionType unionType) {
+        this.unionType = unionType;
+    }
+
+    @Override
+    public IPrinter createPrinter() {
+        return new IPrinter() {
+            private IPrinter[] printers;
+            private List<IAType> unionList;
+
+            @Override
+            public void init() throws HyracksDataException {
+                unionList = unionType.getUnionList();
+                printers = new IPrinter[unionType.getUnionList().size()];
+                for (int i = 0; i < printers.length; i++) {
+                    printers[i] = (LosslessADMJSONPrinterFactoryProvider.INSTANCE
+                            .getPrinterFactory(unionType.getUnionList().get(i))).createPrinter();
+                    printers[i].init();
+                }
+            }
+
+            @Override
+            public void print(byte[] b, int s, int l, PrintStream ps) throws HyracksDataException {
+                ATypeTag tag = unionList.get(b[s + 1]).getTypeTag();
+                if (tag == ATypeTag.UNION) {
+                    printers[b[s + 1]].print(b, s + 1, l, ps);
+                } else {
+                    if (tag == ATypeTag.ANY) {
+                        printers[b[s + 1]].print(b, s + 2, l, ps);
+                    } else {
+                        printers[b[s + 1]].print(b, s + 1, l, ps);
+                    }
+                }
+            }
+        };
+    }
+}
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/AUnorderedlistPrinterFactory.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/AUnorderedlistPrinterFactory.java
new file mode 100644
index 0000000..9b5db41
--- /dev/null
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/AUnorderedlistPrinterFactory.java
@@ -0,0 +1,72 @@
+/*
+ * 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.asterix.dataflow.data.nontagged.printers.json.losslessadm;
+
+import java.io.PrintStream;
+
+import org.apache.asterix.om.pointables.PointableAllocator;
+import org.apache.asterix.om.pointables.base.DefaultOpenFieldType;
+import org.apache.asterix.om.pointables.base.IVisitablePointable;
+import org.apache.asterix.om.pointables.printer.json.losslessadm.APrintVisitor;
+import org.apache.asterix.om.types.ATypeTag;
+import org.apache.asterix.om.types.AUnorderedListType;
+import org.apache.asterix.om.types.IAType;
+import org.apache.hyracks.algebricks.common.utils.Pair;
+import org.apache.hyracks.algebricks.data.IPrinter;
+import org.apache.hyracks.algebricks.data.IPrinterFactory;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+
+public class AUnorderedlistPrinterFactory implements IPrinterFactory {
+
+    private static final long serialVersionUID = 1L;
+    private final AUnorderedListType unorderedlistType;
+
+    public AUnorderedlistPrinterFactory(AUnorderedListType unorderedlistType) {
+        this.unorderedlistType = unorderedlistType;
+    }
+
+    @Override
+    public IPrinter createPrinter() {
+        PointableAllocator allocator = new PointableAllocator();
+        final IAType inputType = unorderedlistType == null
+                ? DefaultOpenFieldType.getDefaultOpenFieldType(ATypeTag.MULTISET) : unorderedlistType;
+        final IVisitablePointable listAccessor = allocator.allocateListValue(inputType);
+        final APrintVisitor printVisitor = new APrintVisitor();
+        final Pair<PrintStream, ATypeTag> arg = new Pair<>(null, null);
+
+        return new IPrinter() {
+            @Override
+            public void init() {
+                arg.second = inputType.getTypeTag();
+            }
+
+            @Override
+            public void print(byte[] b, int start, int l, PrintStream ps) throws HyracksDataException {
+                try {
+                    listAccessor.set(b, start, l);
+                    arg.first = ps;
+                    listAccessor.accept(printVisitor, arg);
+                } catch (Exception e) {
+                    throw HyracksDataException.create(e);
+                }
+            }
+        };
+    }
+}
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/AYearMonthDurationPrinterFactory.java
similarity index 66%
copy from asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java
copy to asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/AYearMonthDurationPrinterFactory.java
index f1c853f..7453a12 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinterFactory.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/losslessadm/AYearMonthDurationPrinterFactory.java
@@ -16,26 +16,23 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+package org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm;
 
-package org.apache.asterix.dataflow.data.nontagged.printers.json.clean;
-
-import java.io.PrintStream;
-
-import org.apache.asterix.om.base.AUUID;
+import org.apache.asterix.dataflow.data.nontagged.serde.AYearMonthDurationSerializerDeserializer;
 import org.apache.hyracks.algebricks.data.IPrinter;
 import org.apache.hyracks.algebricks.data.IPrinterFactory;
 
-public class AUUIDPrinterFactory implements IPrinterFactory {
+public class AYearMonthDurationPrinterFactory implements IPrinterFactory {
 
     private static final long serialVersionUID = 1L;
 
-    public static final AUUIDPrinterFactory INSTANCE = new AUUIDPrinterFactory();
+    public static final AYearMonthDurationPrinterFactory INSTANCE = new AYearMonthDurationPrinterFactory();
 
-    public static final IPrinter PRINTER = (byte[] b, int s, int l, PrintStream ps) -> {
-        StringBuilder buf = new StringBuilder(AUUID.UUID_CHARS + 2);
-        buf.append('"');
-        AUUID.appendLiteralOnly(b, s + 1, buf).append('"');
-        ps.print(buf.toString());
+    public static final IPrinter PRINTER = new ATaggedValuePrinter() {
+        @Override
+        protected void printNonTaggedValue(byte[] b, int s, int l, java.io.PrintStream ps) {
+            ps.print(AYearMonthDurationSerializerDeserializer.getYearMonth(b, s + 1));
+        }
     };
 
     @Override
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/serde/ADoubleSerializerDeserializer.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/serde/ADoubleSerializerDeserializer.java
index 95a4156..be4dcf8 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/serde/ADoubleSerializerDeserializer.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/serde/ADoubleSerializerDeserializer.java
@@ -24,6 +24,7 @@ import java.io.DataOutput;
 import org.apache.asterix.om.base.ADouble;
 import org.apache.hyracks.api.dataflow.value.ISerializerDeserializer;
 import org.apache.hyracks.api.exceptions.HyracksDataException;
+import org.apache.hyracks.data.std.primitive.DoublePointable;
 import org.apache.hyracks.dataflow.common.data.marshalling.DoubleSerializerDeserializer;
 
 public class ADoubleSerializerDeserializer implements ISerializerDeserializer<ADouble> {
@@ -46,10 +47,10 @@ public class ADoubleSerializerDeserializer implements ISerializerDeserializer<AD
     }
 
     public static double getDouble(byte[] bytes, int offset) {
-        return Double.longBitsToDouble(getLongBits(bytes, offset));
+        return DoublePointable.getDouble(bytes, offset);
     }
 
     public static long getLongBits(byte[] bytes, int offset) {
-        return AInt64SerializerDeserializer.getLong(bytes, offset);
+        return DoublePointable.getLongBits(bytes, offset);
     }
 }
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/serde/AFloatSerializerDeserializer.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/serde/AFloatSerializerDeserializer.java
index 95f5e14..970fb6d 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/serde/AFloatSerializerDeserializer.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/serde/AFloatSerializerDeserializer.java
@@ -49,4 +49,8 @@ public class AFloatSerializerDeserializer implements ISerializerDeserializer<AFl
     public static float getFloat(byte[] bytes, int offset) {
         return FloatPointable.getFloat(bytes, offset);
     }
+
+    public static int getIntBits(byte[] bytes, int offset) {
+        return FloatPointable.getIntBits(bytes, offset);
+    }
 }
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/serde/AObjectSerializerDeserializer.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/serde/AObjectSerializerDeserializer.java
index 57f3449..06c2d96 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/serde/AObjectSerializerDeserializer.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/serde/AObjectSerializerDeserializer.java
@@ -27,6 +27,7 @@ import org.apache.asterix.om.base.ABoolean;
 import org.apache.asterix.om.base.ACircle;
 import org.apache.asterix.om.base.ADate;
 import org.apache.asterix.om.base.ADateTime;
+import org.apache.asterix.om.base.ADayTimeDuration;
 import org.apache.asterix.om.base.ADouble;
 import org.apache.asterix.om.base.ADuration;
 import org.apache.asterix.om.base.AFloat;
@@ -46,7 +47,9 @@ import org.apache.asterix.om.base.ARecord;
 import org.apache.asterix.om.base.ARectangle;
 import org.apache.asterix.om.base.AString;
 import org.apache.asterix.om.base.ATime;
+import org.apache.asterix.om.base.AUUID;
 import org.apache.asterix.om.base.AUnorderedList;
+import org.apache.asterix.om.base.AYearMonthDuration;
 import org.apache.asterix.om.base.IAObject;
 import org.apache.asterix.om.types.ATypeTag;
 import org.apache.asterix.om.types.IAType;
@@ -123,6 +126,8 @@ public class AObjectSerializerDeserializer implements ISerializerDeserializer<IA
                 return AUnorderedListSerializerDeserializer.SCHEMALESS_INSTANCE.deserialize(in);
             case GEOMETRY:
                 return AGeometrySerializerDeserializer.INSTANCE.deserialize(in);
+            case UUID:
+                return AUUIDSerializerDeserializer.INSTANCE.deserialize(in);
             default:
                 throw new NotImplementedException("No serializer/deserializer implemented for type " + typeTag + " .");
         }
@@ -180,6 +185,12 @@ public class AObjectSerializerDeserializer implements ISerializerDeserializer<IA
             case DATETIME:
                 ADateTimeSerializerDeserializer.INSTANCE.serialize((ADateTime) instance, out);
                 break;
+            case YEARMONTHDURATION:
+                AYearMonthDurationSerializerDeserializer.INSTANCE.serialize((AYearMonthDuration) instance, out);
+                break;
+            case DAYTIMEDURATION:
+                ADayTimeDurationSerializerDeserializer.INSTANCE.serialize((ADayTimeDuration) instance, out);
+                break;
             case DURATION:
                 ADurationSerializerDeserializer.INSTANCE.serialize((ADuration) instance, out);
                 break;
@@ -219,6 +230,9 @@ public class AObjectSerializerDeserializer implements ISerializerDeserializer<IA
             case GEOMETRY:
                 AGeometrySerializerDeserializer.INSTANCE.serialize((AGeometry) instance, out);
                 break;
+            case UUID:
+                AUUIDSerializerDeserializer.INSTANCE.serialize((AUUID) instance, out);
+                break;
             default:
                 throw new HyracksDataException(
                         "No serializer/deserializer implemented for type " + t.getTypeTag() + " .");
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/formats/base/IDataFormat.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/formats/base/IDataFormat.java
index cab8c22..27b7802 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/formats/base/IDataFormat.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/formats/base/IDataFormat.java
@@ -65,6 +65,8 @@ public interface IDataFormat {
 
     public IPrinterFactoryProvider getCleanJSONPrinterFactoryProvider();
 
+    public IPrinterFactoryProvider getLosslessADMJSONPrinterFactoryProvider();
+
     public IMissingWriterFactory getMissingWriterFactory();
 
     public IUnnestingPositionWriterFactory getUnnestingPositionWriterFactory();
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/formats/nontagged/LosslessADMJSONPrinterFactoryProvider.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/formats/nontagged/LosslessADMJSONPrinterFactoryProvider.java
new file mode 100644
index 0000000..e70b6b1
--- /dev/null
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/formats/nontagged/LosslessADMJSONPrinterFactoryProvider.java
@@ -0,0 +1,226 @@
+/*
+ * 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.asterix.formats.nontagged;
+
+import org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm.ABinaryPrinterFactory;
+import org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm.ABooleanPrinterFactory;
+import org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm.ACirclePrinterFactory;
+import org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm.ADatePrinterFactory;
+import org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm.ADateTimePrinterFactory;
+import org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm.ADayTimeDurationPrinterFactory;
+import org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm.ADoublePrinterFactory;
+import org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm.ADurationPrinterFactory;
+import org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm.AFloatPrinterFactory;
+import org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm.AInt16PrinterFactory;
+import org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm.AInt32PrinterFactory;
+import org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm.AInt64PrinterFactory;
+import org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm.AInt8PrinterFactory;
+import org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm.ALinePrinterFactory;
+import org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm.AMissingPrinterFactory;
+import org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm.ANullPrinterFactory;
+import org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm.AObjectPrinterFactory;
+import org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm.AOptionalFieldPrinterFactory;
+import org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm.AOrderedlistPrinterFactory;
+import org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm.APoint3DPrinterFactory;
+import org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm.APointPrinterFactory;
+import org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm.APolygonPrinterFactory;
+import org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm.ARecordPrinterFactory;
+import org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm.ARectanglePrinterFactory;
+import org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm.AStringPrinterFactory;
+import org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm.ATimePrinterFactory;
+import org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm.AUUIDPrinterFactory;
+import org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm.AUnionPrinterFactory;
+import org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm.AUnorderedlistPrinterFactory;
+import org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm.AYearMonthDurationPrinterFactory;
+import org.apache.asterix.om.base.ABinary;
+import org.apache.asterix.om.base.ACircle;
+import org.apache.asterix.om.base.ADate;
+import org.apache.asterix.om.base.ADateTime;
+import org.apache.asterix.om.base.ADayTimeDuration;
+import org.apache.asterix.om.base.ADuration;
+import org.apache.asterix.om.base.ALine;
+import org.apache.asterix.om.base.APoint;
+import org.apache.asterix.om.base.APoint3D;
+import org.apache.asterix.om.base.APolygon;
+import org.apache.asterix.om.base.ARectangle;
+import org.apache.asterix.om.base.ATime;
+import org.apache.asterix.om.base.AUUID;
+import org.apache.asterix.om.base.AYearMonthDuration;
+import org.apache.asterix.om.types.AOrderedListType;
+import org.apache.asterix.om.types.ARecordType;
+import org.apache.asterix.om.types.ATypeTag;
+import org.apache.asterix.om.types.AUnionType;
+import org.apache.asterix.om.types.AUnorderedListType;
+import org.apache.asterix.om.types.IAType;
+import org.apache.hyracks.algebricks.data.IPrinterFactory;
+import org.apache.hyracks.algebricks.data.IPrinterFactoryProvider;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+
+/**
+ * Printer for the Lossless-ADM-JSON format.
+ * <p/>
+ * Format specification:
+ * <p/>
+ * <ul>
+ * <li>Record is printed as JSON object
+ * <li>Array or multiset is printed as JSON array
+ * <li>Primitive types are printed as JSON strings in the following format: {@code "TC:encoded_value"}. <br/>
+ *     TC is a two-character type code returned by {@link ATypeTag#serialize()} printed in hexadecimal format, <br/>
+ *     ':' is a separator character, <br/>
+ *     {@code encoded_value} is a type-specific text. <br/>
+ *     This is a generic primitive type encoding that works for all primitive types.
+ *     Null, Boolean, Int64, and String types types are printed in their special simplified form describe below.
+ *     Lossless-ADM-JSON parser is supposed to read both forms for these types: generic and simplified.
+ * </ul>
+ *
+ * <p/>
+ * encoded_value format in the generic form:
+ * <ul>
+ * <li>Int8, Int16, Int32: integer number
+ * <li>Float, Double: integer number corresponding to IEEE 754 floating-point layout</li>
+ * <li>Date: integer number returned by {@link ADate#getChrononTimeInDays()}</li>
+ * <li>Time: integer number returned by {@link ATime#getChrononTime()}</li>
+ * <li>DateTime: integer number returned by {@link ADateTime#getChrononTime()} </li>
+ * <li>YearMonthDuration: integer number returned by {@link AYearMonthDuration#getMonths()}</li>
+ * <li>DayTimeDuration: integer number returned by {@link ADayTimeDuration#getMilliseconds()}</li>
+ * <li>Duration: int1:int2, where int1 is {@link ADuration#getMonths()} and int2 is {@link ADuration#getMilliseconds()}</li>
+ * <li>Binary: {@link ABinary#getBytes()} encoded as Base64</li>
+ * <li>UUID: textual form produced by {@link AUUID#appendLiteralOnly(Appendable)}</li>
+ * <li>Missing: N/A. The two character type code (TC) is sufficient to encode this type. ':' separator character is not printed</li>
+ * <li>Point: int1:int2, where int1 and int2 are integer numbers corresponding to IEEE 754 floating-point layout of
+ *     {@link APoint#getX()} and {@link APoint#getY()}</li>
+ * <li>Point3D: int1:int2:int3, where int1 and int2, and int3 are integer numbers corresponding to IEEE 754 floating-point layouts of
+ *     {@link APoint3D#getX()} and {@link APoint3D#getY()}, and {@link APoint3D#getZ()}</li>
+ * <li>Circle: int1:int2:int3 - integer numbers corresponding to IEEE 754 floating-point layouts of {@link ACircle#getP()} (getX()/getY()) and {@link ACircle#getRadius()}</li>
+ * <li>Line: int1:int2:int3:int4 - integer numbers corresponding to IEEE 754 floating-point layouts of {@link ALine#getP1()} (getX(), getY()) and {@link ALine#getP2()} (getX(), getY())</li>
+ * <li>Rectangle:  int1:int2:int3:int4 - integer numbers corresponding to IEEE 754 floating-point layouts of {@link ARectangle#getP1()} (getX(), getY()) and {@link ARectangle#getP2()} (getX(), getY())</li></li>
+ * <li>Polygon: int0:int1:int2:..intN - integer numbers where int0 is the number of points and each subsequent integer pair corresponds to IEEE 754 floating-point layouts of each point returned by {@link APolygon#getPoints()}</li>
+ * </ul>
+ *
+ * Simplified form for {@code Null}, {@code Boolean}, {@code Int64}, and {@code String} types:
+ * <ul>
+ * <li>Null is printed as JSON null
+ * <li>Boolean value is printed as JSON boolean
+ * <li>Int64 value is printed as JSON number
+ * <li>String value is printed as ":string_text". Empty string is printed as "".
+ * </ul>
+ *
+ * Generic encoded_value form for {@code Null}, {@code Boolean}, {@code Int64}, and {@code String} types
+ * <ul>
+ * <li>Null: N/A. The two character type code (TC) is sufficient to encode this type. ':' separator character is not printed</li>
+ * <li>Boolean: integer number. 0=false, non-0=true
+ * <li>Int64: integer number
+ * <li>String: string text as is
+ * </ul>
+ */
+public class LosslessADMJSONPrinterFactoryProvider implements IPrinterFactoryProvider {
+
+    public static final LosslessADMJSONPrinterFactoryProvider INSTANCE = new LosslessADMJSONPrinterFactoryProvider();
+
+    private LosslessADMJSONPrinterFactoryProvider() {
+    }
+
+    @Override
+    public IPrinterFactory getPrinterFactory(Object typeInfo) throws HyracksDataException {
+        IAType type = (IAType) typeInfo;
+
+        if (type != null) {
+            switch (type.getTypeTag()) {
+                case TINYINT:
+                    return AInt8PrinterFactory.INSTANCE;
+                case SMALLINT:
+                    return AInt16PrinterFactory.INSTANCE;
+                case INTEGER:
+                    return AInt32PrinterFactory.INSTANCE;
+                case BIGINT:
+                    return AInt64PrinterFactory.INSTANCE;
+                case MISSING:
+                    return AMissingPrinterFactory.INSTANCE;
+                case NULL:
+                    return ANullPrinterFactory.INSTANCE;
+                case BOOLEAN:
+                    return ABooleanPrinterFactory.INSTANCE;
+                case FLOAT:
+                    return AFloatPrinterFactory.INSTANCE;
+                case DOUBLE:
+                    return ADoublePrinterFactory.INSTANCE;
+                case TIME:
+                    return ATimePrinterFactory.INSTANCE;
+                case DATE:
+                    return ADatePrinterFactory.INSTANCE;
+                case DATETIME:
+                    return ADateTimePrinterFactory.INSTANCE;
+                case DURATION:
+                    return ADurationPrinterFactory.INSTANCE;
+                case YEARMONTHDURATION:
+                    return AYearMonthDurationPrinterFactory.INSTANCE;
+                case DAYTIMEDURATION:
+                    return ADayTimeDurationPrinterFactory.INSTANCE;
+                case STRING:
+                    return AStringPrinterFactory.INSTANCE;
+                case BINARY:
+                    return ABinaryPrinterFactory.INSTANCE;
+                case UUID:
+                    return AUUIDPrinterFactory.INSTANCE;
+                case POINT:
+                    return APointPrinterFactory.INSTANCE;
+                case POINT3D:
+                    return APoint3DPrinterFactory.INSTANCE;
+                case CIRCLE:
+                    return ACirclePrinterFactory.INSTANCE;
+                case LINE:
+                    return ALinePrinterFactory.INSTANCE;
+                case RECTANGLE:
+                    return ARectanglePrinterFactory.INSTANCE;
+                case POLYGON:
+                    return APolygonPrinterFactory.INSTANCE;
+                case OBJECT:
+                    return new ARecordPrinterFactory((ARecordType) type);
+                case ARRAY:
+                    return new AOrderedlistPrinterFactory((AOrderedListType) type);
+                case MULTISET:
+                    return new AUnorderedlistPrinterFactory((AUnorderedListType) type);
+                case UNION:
+                    if (((AUnionType) type).isUnknownableType()) {
+                        return new AOptionalFieldPrinterFactory((AUnionType) type);
+                    } else {
+                        return new AUnionPrinterFactory((AUnionType) type);
+                    }
+                case GEOMETRY:
+                case INTERVAL:
+                    // NYI
+                case SHORTWITHOUTTYPEINFO:
+                case ANY:
+                case BITARRAY:
+                case ENUM:
+                case SPARSOBJECT:
+                case SYSTEM_NULL:
+                case TYPE:
+                case UINT16:
+                case UINT32:
+                case UINT64:
+                case UINT8:
+                    // These types are not intended to be printed to the user.
+                    break;
+            }
+        }
+        return AObjectPrinterFactory.INSTANCE;
+    }
+}
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/AOrderedList.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/AOrderedList.java
index 785c62d..9ec73ee 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/AOrderedList.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/AOrderedList.java
@@ -79,7 +79,7 @@ public class AOrderedList implements IACollection {
             return false;
         } else {
             AOrderedList y = (AOrderedList) o;
-            return InMemUtils.cursorEquals(this.getCursor(), y.getCursor());
+            return InMemUtils.deepEqualCursors(this.getCursor(), y.getCursor());
         }
     }
 
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/AUUID.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/AUUID.java
index 10c2157..fb44db2 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/AUUID.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/AUUID.java
@@ -84,29 +84,38 @@ public class AUUID implements IAObject {
 
     @Override
     public String toString() {
-        StringBuilder buf = new StringBuilder(UUID_CHARS + 9);
-        buf.append("uuid: { ");
-        return appendLiteralOnly(buf).append(" }").toString();
+        try {
+            StringBuilder buf = new StringBuilder(UUID_CHARS + 9);
+            buf.append("uuid: { ");
+            appendLiteralOnly(buf);
+            buf.append(" }");
+            return buf.toString();
+        } catch (IOException e) {
+            throw new IllegalStateException(e);
+        }
     }
 
-    public StringBuilder appendLiteralOnly(StringBuilder buf) {
-        return appendLiteralOnly(uuidBytes, 0, buf);
+    public void appendLiteralOnly(Appendable buf) throws IOException {
+        appendLiteralOnly(uuidBytes, 0, buf);
     }
 
-    private static StringBuilder digits(byte b[], int offset, int count, StringBuilder result) {
+    private static void digits(byte b[], int offset, int count, Appendable result) throws IOException {
         for (int i = 0; i < count; i++) {
             result.append(CHARS[(b[offset + i] >> 4) & 0xf]);
             result.append(CHARS[b[offset + i] & 0xf]);
         }
-        return result;
     }
 
-    public static StringBuilder appendLiteralOnly(byte[] bytes, int offset, StringBuilder result) {
-        digits(bytes, offset, 4, result).append('-');
-        digits(bytes, offset + 4, 2, result).append('-');
-        digits(bytes, offset + 6, 2, result).append('-');
-        digits(bytes, offset + 8, 2, result).append('-');
-        return digits(bytes, offset + 10, 6, result);
+    public static void appendLiteralOnly(byte[] bytes, int offset, Appendable result) throws IOException {
+        digits(bytes, offset, 4, result);
+        result.append('-');
+        digits(bytes, offset + 4, 2, result);
+        result.append('-');
+        digits(bytes, offset + 6, 2, result);
+        result.append('-');
+        digits(bytes, offset + 8, 2, result);
+        result.append('-');
+        digits(bytes, offset + 10, 6, result);
     }
 
     public void writeTo(DataOutput out) throws HyracksDataException {
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/AUnorderedList.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/AUnorderedList.java
index 137171d..bd4586a 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/AUnorderedList.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/AUnorderedList.java
@@ -56,7 +56,7 @@ public class AUnorderedList implements IACollection {
             return false;
         } else {
             AUnorderedList y = (AUnorderedList) o;
-            return InMemUtils.cursorEquals(this.getCursor(), y.getCursor());
+            return InMemUtils.deepEqualCursors(this.getCursor(), y.getCursor());
         }
     }
 
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/InMemUtils.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/InMemUtils.java
index 65c7e61..af0cb0d 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/InMemUtils.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/InMemUtils.java
@@ -20,14 +20,14 @@ package org.apache.asterix.om.base;
 
 public class InMemUtils {
 
-    public final static boolean cursorEquals(IACursor c1, IACursor c2) {
+    public final static boolean deepEqualCursors(IACursor c1, IACursor c2) {
         while (c1.next()) {
             if (!(c2.next())) {
                 return false;
             }
             IAObject thisO = c1.get();
             IAObject otherO = c2.get();
-            if (!(thisO.equals(otherO))) {
+            if (!(thisO.deepEqual(otherO))) {
                 return false;
             }
         }
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/temporal/ADurationParserFactory.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/temporal/ADurationParserFactory.java
index ec387e2..657a66e 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/temporal/ADurationParserFactory.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/temporal/ADurationParserFactory.java
@@ -28,6 +28,7 @@ import org.apache.asterix.om.base.IAObject;
 import org.apache.hyracks.api.exceptions.HyracksDataException;
 import org.apache.hyracks.dataflow.common.data.parsers.IValueParser;
 import org.apache.hyracks.dataflow.common.data.parsers.IValueParserFactory;
+import org.apache.hyracks.util.StringUtil;
 
 public class ADurationParserFactory implements IValueParserFactory {
 
@@ -83,64 +84,48 @@ public class ADurationParserFactory implements IValueParserFactory {
         All
     }
 
-    interface IStringAccessor {
-        char getCharAt(int index);
+    public static void parseDuration(CharSequence durationString, final int start, int length, IAObject mutableObject,
+            ADurationParseOption parseOption) throws HyracksDataException {
+        parseDuration(durationString, start, length, mutableObject, parseOption, StringUtil.getCharSequenceAccessor());
+    }
+
+    public static void parseDuration(char[] durationString, final int start, int length, IAObject mutableObject,
+            ADurationParseOption parseOption) throws HyracksDataException {
+        parseDuration(durationString, start, length, mutableObject, parseOption, StringUtil.getCharArrayAccessor());
     }
 
-    public static void parseDuration(final Object durationString, final int start, int length, IAObject mutableObject,
+    public static void parseDuration(byte[] durationString, final int start, int length, IAObject mutableObject,
             ADurationParseOption parseOption) throws HyracksDataException {
+        parseDuration(durationString, start, length, mutableObject, parseOption,
+                StringUtil.getByteArrayAsCharAccessor());
+    }
+
+    public static <T> void parseDuration(T durationString, final int start, int length, IAObject mutableObject,
+            ADurationParseOption parseOption, StringUtil.ICharAccessor<T> charAccessor) throws HyracksDataException {
 
         int offset = 0;
         int value = 0, hour = 0, minute = 0, second = 0, millisecond = 0, year = 0, month = 0, day = 0;
         State state = State.NOTHING_READ;
 
-        IStringAccessor charAccessor;
-
-        if (durationString instanceof char[]) {
-            charAccessor = new IStringAccessor() {
-                @Override
-                public char getCharAt(int index) {
-                    return ((char[]) durationString)[start + index];
-                }
-            };
-        } else if (durationString instanceof byte[]) {
-            charAccessor = new IStringAccessor() {
-
-                @Override
-                public char getCharAt(int index) {
-                    return (char) (((byte[]) durationString)[start + index]);
-                }
-            };
-        } else if (durationString instanceof String) {
-            charAccessor = new IStringAccessor() {
-
-                @Override
-                public char getCharAt(int index) {
-                    return ((String) durationString).charAt(start + index);
-                }
-            };
-        } else {
-            throw new HyracksDataException(durationErrorMessage);
-        }
-
         short sign = 1;
-        if (charAccessor.getCharAt(offset) == '-') {
+        if (charAccessor.charAt(durationString, start + offset) == '-') {
             offset++;
             sign = -1;
         }
 
-        if (charAccessor.getCharAt(offset) != 'P') {
+        if (charAccessor.charAt(durationString, start + offset) != 'P') {
             throw new HyracksDataException(durationErrorMessage + ": Missing leading 'P'.");
         }
 
         offset++;
 
         for (; offset < length; offset++) {
-            if (charAccessor.getCharAt(offset) >= '0' && charAccessor.getCharAt(offset) <= '9') {
+            if (charAccessor.charAt(durationString, start + offset) >= '0'
+                    && charAccessor.charAt(durationString, start + offset) <= '9') {
                 // accumulate the digit fields
-                value = value * DECIMAL_UNIT + charAccessor.getCharAt(offset) - '0';
+                value = value * DECIMAL_UNIT + charAccessor.charAt(durationString, start + offset) - '0';
             } else {
-                switch (charAccessor.getCharAt(offset)) {
+                switch (charAccessor.charAt(durationString, start + offset)) {
                     case 'Y':
                         if (state.compareTo(State.YEAR) < 0) {
                             if (parseOption == ADurationParseOption.DAY_TIME) {
@@ -213,11 +198,11 @@ public class ADurationParserFactory implements IValueParserFactory {
                             }
                             int i = 1;
                             for (; offset + i < length; i++) {
-                                if (charAccessor.getCharAt(offset + i) >= '0'
-                                        && charAccessor.getCharAt(offset + i) <= '9') {
+                                if (charAccessor.charAt(durationString, start + offset + i) >= '0'
+                                        && charAccessor.charAt(durationString, start + offset + i) <= '9') {
                                     if (i < 4) {
-                                        millisecond =
-                                                millisecond * DECIMAL_UNIT + (charAccessor.getCharAt(offset + i) - '0');
+                                        millisecond = millisecond * DECIMAL_UNIT
+                                                + (charAccessor.charAt(durationString, start + offset + i) - '0');
                                     } else {
                                         throw new HyracksDataException(
                                                 durationErrorMessage + ": wrong MILLISECOND field.");
@@ -276,6 +261,8 @@ public class ADurationParserFactory implements IValueParserFactory {
             ((AMutableYearMonthDuration) mutableObject).setMonths(totalMonths);
         } else if (mutableObject instanceof AMutableDayTimeDuration) {
             ((AMutableDayTimeDuration) mutableObject).setMilliseconds(totalMilliseconds);
+        } else {
+            throw new IllegalArgumentException();
         }
     }
 }
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/pointables/printer/AListPrinter.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/pointables/printer/AListPrinter.java
index d1f6ab7..3fd23f7 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/pointables/printer/AListPrinter.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/pointables/printer/AListPrinter.java
@@ -74,7 +74,11 @@ public class AListPrinter {
         IVisitablePointable item = items.get(i);
         ATypeTag typeTag = EnumDeserializer.ATYPETAGDESERIALIZER
                 .deserialize(itemTypeTag.getByteArray()[itemTypeTag.getStartOffset()]);
-        itemVisitorArg.second = item.getLength() <= 1 ? ATypeTag.NULL : typeTag;
+        itemVisitorArg.second = getItemTypeTag(item, typeTag);
         item.accept(visitor, itemVisitorArg);
     }
+
+    protected ATypeTag getItemTypeTag(IVisitablePointable item, ATypeTag typeTag) {
+        return item.getLength() <= 1 ? ATypeTag.NULL : typeTag;
+    }
 }
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/pointables/printer/ARecordPrinter.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/pointables/printer/ARecordPrinter.java
index 3858bd6..7823637 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/pointables/printer/ARecordPrinter.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/pointables/printer/ARecordPrinter.java
@@ -86,11 +86,18 @@ public class ARecordPrinter {
             IVisitablePointable fieldValue, ATypeTag fieldTypeTag) throws HyracksDataException {
         itemVisitorArg.second = fieldTypeTag;
         if (fieldNameSeparator != null) {
-            // print field name
-            fieldName.accept(visitor, nameVisitorArg);
+            printFieldName(ps, visitor, fieldName);
             ps.print(fieldNameSeparator);
         }
-        // print field value
+        printFieldValue(visitor, fieldValue);
+    }
+
+    protected void printFieldName(PrintStream ps, IPrintVisitor visitor, IVisitablePointable fieldName)
+            throws HyracksDataException {
+        fieldName.accept(visitor, nameVisitorArg);
+    }
+
+    protected void printFieldValue(IPrintVisitor visitor, IVisitablePointable fieldValue) throws HyracksDataException {
         fieldValue.accept(visitor, itemVisitorArg);
     }
 }
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/pointables/printer/json/losslessadm/APrintVisitor.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/pointables/printer/json/losslessadm/APrintVisitor.java
new file mode 100644
index 0000000..025590b
--- /dev/null
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/pointables/printer/json/losslessadm/APrintVisitor.java
@@ -0,0 +1,67 @@
+/*
+ * 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.asterix.om.pointables.printer.json.losslessadm;
+
+import java.io.PrintStream;
+
+import org.apache.asterix.dataflow.data.nontagged.printers.json.losslessadm.AObjectPrinterFactory;
+import org.apache.asterix.om.pointables.AListVisitablePointable;
+import org.apache.asterix.om.pointables.ARecordVisitablePointable;
+import org.apache.asterix.om.pointables.base.IVisitablePointable;
+import org.apache.asterix.om.pointables.printer.AListPrinter;
+import org.apache.asterix.om.pointables.printer.ARecordPrinter;
+import org.apache.asterix.om.pointables.printer.AbstractPrintVisitor;
+import org.apache.asterix.om.pointables.printer.IPrintVisitor;
+import org.apache.asterix.om.types.ATypeTag;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+
+public class APrintVisitor extends AbstractPrintVisitor {
+
+    private final org.apache.asterix.om.pointables.printer.json.clean.APrintVisitor cleanPrintVisitor =
+            new org.apache.asterix.om.pointables.printer.json.clean.APrintVisitor();
+
+    @Override
+    protected AListPrinter createListPrinter(AListVisitablePointable accessor) {
+        return new AListPrinter("[ ", " ]", ", ") {
+            @Override
+            protected ATypeTag getItemTypeTag(IVisitablePointable item, ATypeTag typeTag) {
+                // avoid MISSING to NULL conversion, because we print MISSING as is in this format
+                return typeTag;
+            }
+        };
+    }
+
+    @Override
+    protected ARecordPrinter createRecordPrinter(ARecordVisitablePointable accessor) {
+        return new ARecordPrinter("{ ", " }", ", ", ": ") {
+            @Override
+            protected void printFieldName(PrintStream ps, IPrintVisitor visitor, IVisitablePointable fieldName)
+                    throws HyracksDataException {
+                super.printFieldName(ps, cleanPrintVisitor, fieldName);
+            }
+        };
+    }
+
+    @Override
+    protected boolean printFlatValue(ATypeTag typeTag, byte[] b, int s, int l, PrintStream ps)
+            throws HyracksDataException {
+        return AObjectPrinterFactory.printFlatValue(typeTag, b, s, l, ps);
+    }
+}
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/common/NumberUtils.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/common/NumberUtils.java
index 7a02fd2..19bff61 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/common/NumberUtils.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/common/NumberUtils.java
@@ -26,6 +26,7 @@ import org.apache.asterix.om.base.AMutableInt32;
 import org.apache.asterix.om.base.AMutableInt64;
 import org.apache.asterix.om.base.AMutableInt8;
 import org.apache.hyracks.data.std.primitive.UTF8StringPointable;
+import org.apache.hyracks.util.StringUtil;
 
 /**
  * Utility methods for number handling
@@ -103,26 +104,34 @@ public final class NumberUtils {
     public static boolean parseInt64(UTF8StringPointable textPtr, AMutableInt64 result) {
         byte[] bytes = textPtr.getByteArray();
         int offset = textPtr.getCharStartOffset();
+        int end = textPtr.getStartOffset() + textPtr.getLength();
+        return parseInt64(bytes, offset, end, StringUtil.getByteArrayAsCharAccessor(), result);
+    }
+
+    public static <T> boolean parseInt64(T input, int begin, int end, StringUtil.ICharAccessor<T> charAccessor,
+            AMutableInt64 result) {
+        int offset = begin;
         //accumulating value in negative domain
         //otherwise Long.MIN_VALUE = -(Long.MAX_VALUE + 1) would have caused overflow
         long value = 0;
         boolean positive = true;
         long limit = -Long.MAX_VALUE;
-        if (bytes[offset] == '+') {
+        char c = charAccessor.charAt(input, offset);
+        if (c == '+') {
             offset++;
-        } else if (bytes[offset] == '-') {
+        } else if (c == '-') {
             offset++;
             positive = false;
             limit = Long.MIN_VALUE;
         }
-        int end = textPtr.getStartOffset() + textPtr.getLength();
         for (; offset < end; offset++) {
             int digit;
-            if (bytes[offset] >= '0' && bytes[offset] <= '9') {
+            c = charAccessor.charAt(input, offset);
+            if (c >= '0' && c <= '9') {
                 value *= 10;
-                digit = bytes[offset] - '0';
-            } else if (bytes[offset] == 'i' && bytes[offset + 1] == '6' && bytes[offset + 2] == '4'
-                    && offset + 3 == end) {
+                digit = c - '0';
+            } else if (c == 'i' && charAccessor.charAt(input, offset + 1) == '6'
+                    && charAccessor.charAt(input, offset + 2) == '4' && offset + 3 == end) {
                 break;
             } else {
                 return false;
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/formats/NonTaggedDataFormat.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/formats/NonTaggedDataFormat.java
index 05d14b8..f2685f4 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/formats/NonTaggedDataFormat.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/formats/NonTaggedDataFormat.java
@@ -33,6 +33,7 @@ import org.apache.asterix.formats.nontagged.BinaryHashFunctionFamilyProvider;
 import org.apache.asterix.formats.nontagged.BinaryIntegerInspector;
 import org.apache.asterix.formats.nontagged.CSVPrinterFactoryProvider;
 import org.apache.asterix.formats.nontagged.CleanJSONPrinterFactoryProvider;
+import org.apache.asterix.formats.nontagged.LosslessADMJSONPrinterFactoryProvider;
 import org.apache.asterix.formats.nontagged.LosslessJSONPrinterFactoryProvider;
 import org.apache.asterix.formats.nontagged.NormalizedKeyComputerFactoryProvider;
 import org.apache.asterix.formats.nontagged.PredicateEvaluatorFactoryProvider;
@@ -300,6 +301,11 @@ public class NonTaggedDataFormat implements IDataFormat {
     }
 
     @Override
+    public IPrinterFactoryProvider getLosslessADMJSONPrinterFactoryProvider() {
+        return LosslessADMJSONPrinterFactoryProvider.INSTANCE;
+    }
+
+    @Override
     public IPrinterFactoryProvider getCleanJSONPrinterFactoryProvider() {
         return CleanJSONPrinterFactoryProvider.INSTANCE;
     }
diff --git a/asterixdb/asterix-test-framework/src/main/java/org/apache/asterix/testframework/context/TestCaseContext.java b/asterixdb/asterix-test-framework/src/main/java/org/apache/asterix/testframework/context/TestCaseContext.java
index c73434d..6e458a4 100644
--- a/asterixdb/asterix-test-framework/src/main/java/org/apache/asterix/testframework/context/TestCaseContext.java
+++ b/asterixdb/asterix-test-framework/src/main/java/org/apache/asterix/testframework/context/TestCaseContext.java
@@ -254,6 +254,7 @@ public class TestCaseContext {
         NONE("", ""),
         ADM("adm", "application/x-adm"),
         LOSSLESS_JSON("json", "application/json; lossless=true"),
+        LOSSLESS_ADM_JSON("json", "application/json; lossless-adm=true"),
         CLEAN_JSON("json", "application/json"),
         CSV("csv", "text/csv"),
         CSV_HEADER("csv-header", "text/csv; header=present"),
@@ -284,6 +285,8 @@ public class TestCaseContext {
                     return OutputFormat.ADM;
                 case LOSSLESS_JSON:
                     return OutputFormat.LOSSLESS_JSON;
+                case LOSSLESS_ADM_JSON:
+                    return OutputFormat.LOSSLESS_ADM_JSON;
                 case CLEAN_JSON:
                     return OutputFormat.CLEAN_JSON;
                 case CSV:
diff --git a/asterixdb/asterix-test-framework/src/main/resources/Catalog.xsd b/asterixdb/asterix-test-framework/src/main/resources/Catalog.xsd
index 4ea9e0e..303a4d7 100644
--- a/asterixdb/asterix-test-framework/src/main/resources/Catalog.xsd
+++ b/asterixdb/asterix-test-framework/src/main/resources/Catalog.xsd
@@ -252,6 +252,7 @@
          <xs:enumeration value="Ignore"/>
          <xs:enumeration value="Clean-JSON"/>
          <xs:enumeration value="Lossless-JSON"/>
+         <xs:enumeration value="Lossless-ADM-JSON"/>
          <xs:enumeration value="CSV"/>
          <xs:enumeration value="CSV_Header"/>
          <xs:enumeration value="AST"/>
diff --git a/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/FloatPointable.java b/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/FloatPointable.java
index 289e441..7c72d5c 100644
--- a/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/FloatPointable.java
+++ b/hyracks-fullstack/hyracks/hyracks-data/hyracks-data-std/src/main/java/org/apache/hyracks/data/std/primitive/FloatPointable.java
@@ -62,7 +62,7 @@ public final class FloatPointable extends AbstractPointable implements IHashable
         }
     }
 
-    private static int getIntBits(byte[] bytes, int start) {
+    public static int getIntBits(byte[] bytes, int start) {
         return IntegerPointable.getInteger(bytes, start);
     }
 
diff --git a/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/StringUtil.java b/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/StringUtil.java
index 78155c9..df33f6b 100644
--- a/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/StringUtil.java
+++ b/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/StringUtil.java
@@ -50,4 +50,21 @@ public class StringUtil {
         }
         return sb.toString();
     }
+
+    @FunctionalInterface
+    public interface ICharAccessor<T> {
+        char charAt(T input, int index);
+    }
+
+    public static ICharAccessor<CharSequence> getCharSequenceAccessor() {
+        return CharSequence::charAt;
+    }
+
+    public static ICharAccessor<char[]> getCharArrayAccessor() {
+        return (input, index) -> input[index];
+    }
+
+    public static ICharAccessor<byte[]> getByteArrayAsCharAccessor() {
+        return (input, index) -> (char) input[index];
+    }
 }
diff --git a/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/bytes/Base64Parser.java b/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/bytes/Base64Parser.java
index 9f527e9..c47d47a 100644
--- a/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/bytes/Base64Parser.java
+++ b/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/bytes/Base64Parser.java
@@ -21,6 +21,8 @@ package org.apache.hyracks.util.bytes;
 
 import java.util.Arrays;
 
+import org.apache.hyracks.util.StringUtil;
+
 public class Base64Parser {
     private static final byte[] DECODE_MAP = initDecodeMap();
     private static final byte PADDING = 127;
@@ -52,6 +54,21 @@ public class Base64Parser {
 
     /**
      * Parse the Base64 sequence from {@code input} into {@code out}
+     * Note, the out should have enough space by checking the {@link #guessLength(byte[], int, int)} first
+     *
+     * @param input
+     * @param start
+     * @param length
+     * @param out
+     * @param offset
+     * @return the number of written bytes
+     */
+    public int parseBase64String(byte[] input, int start, int length, byte[] out, int offset) {
+        return parseBase64String(input, start, length, StringUtil.getByteArrayAsCharAccessor(), out, offset);
+    }
+
+    /**
+     * Parse the Base64 sequence from {@code input} into {@code out}
      * Note, the out should have enough space by checking the {@link #guessLength(char[], int, int)} first
      *
      * @param input
@@ -62,42 +79,37 @@ public class Base64Parser {
      * @return
      */
     public int parseBase64String(char[] input, int start, int length, byte[] out, int offset) {
-        int outLength = 0;
-
-        int i;
-        int q = 0;
-
-        // convert each quadruplet to three bytes.
-        for (i = 0; i < length; i++) {
-            char ch = input[start + i];
-            byte v = DECODE_MAP[ch];
-
-            if (v == -1) {
-                throw new IllegalArgumentException("Invalid Base64 character");
-            }
-            quadruplet[q++] = v;
-
-            if (q == 4) {
-                outLength += dumpQuadruplet(out, offset + outLength);
-                q = 0;
-            }
-        }
+        return parseBase64String(input, start, length, StringUtil.getCharArrayAccessor(), out, offset);
+    }
 
-        return outLength;
+    /**
+     * Parse the Base64 sequence from {@code input} into {@code out}
+     * Note, the out should have enough space by checking the {@link #guessLength(CharSequence, int, int)} first
+     *
+     * @param input
+     * @param start
+     * @param length
+     * @param out
+     * @param offset
+     * @return
+     */
+    public int parseBase64String(CharSequence input, int start, int length, byte[] out, int offset) {
+        return parseBase64String(input, start, length, StringUtil.getCharSequenceAccessor(), out, offset);
     }
 
     /**
      * Parse the Base64 sequence from {@code input} into {@code out}
-     * Note, the out should have enough space by checking the {@link #guessLength(byte[], int, int)} first
+     * Note, the out should have enough space by checking the {@link #guessLength(char[], int, int)} first
      *
      * @param input
      * @param start
      * @param length
      * @param out
      * @param offset
-     * @return the number of written bytes
+     * @return
      */
-    public int parseBase64String(byte[] input, int start, int length, byte[] out, int offset) {
+    private <T> int parseBase64String(T input, int start, int length, StringUtil.ICharAccessor<T> stringAccessor,
+            byte[] out, int offset) {
         int outLength = 0;
 
         int i;
@@ -105,7 +117,7 @@ public class Base64Parser {
 
         // convert each quadruplet to three bytes.
         for (i = 0; i < length; i++) {
-            char ch = (char) input[start + i];
+            char ch = stringAccessor.charAt(input, start + i);
             byte v = DECODE_MAP[ch];
 
             if (v == -1) {
@@ -136,40 +148,66 @@ public class Base64Parser {
      * (like what most web services produce), then the speculation of this method
      * will be correct, so we get the performance benefit.
      */
-    public static int guessLength(char[] chars, int start, int length) {
-
-        // compute the tail '=' chars
-        int j = length - 1;
-        for (; j >= 0; j--) {
-            byte code = DECODE_MAP[chars[start + j]];
-            if (code == PADDING) {
-                continue;
-            }
-            if (code == -1) // most likely this base64 text is indented. go with the upper bound
-            {
-                return length / 4 * 3;
-            }
-            break;
-        }
-
-        j++; // text.charAt(j) is now at some base64 char, so +1 to make it the size
-        int padSize = length - j;
-        if (padSize > 2) // something is wrong with base64. be safe and go with the upper bound
-        {
-            return length / 4 * 3;
-        }
+    public static int guessLength(byte[] input, int start, int length) {
+        return guessLength(input, start, length, StringUtil.getByteArrayAsCharAccessor());
+    }
 
-        // so far this base64 looks like it's unindented tightly packed base64.
-        // take a chance and create an array with the expected size
-        return length / 4 * 3 - padSize;
+    /**
+     * computes the length of binary data speculatively.
+     * Our requirement is to create byte[] of the exact length to store the binary data.
+     * If we do this in a straight-forward way, it takes two passes over the data.
+     * Experiments show that this is a non-trivial overhead (35% or so is spent on
+     * the first pass in calculating the length.)
+     * So the approach here is that we compute the length speculatively, without looking
+     * at the whole contents. The obtained speculative value is never less than the
+     * actual length of the binary data, but it may be bigger. So if the speculation
+     * goes wrong, we'll pay the cost of reallocation and buffer copying.
+     * If the base64 text is tightly packed with no indentation nor illegal char
+     * (like what most web services produce), then the speculation of this method
+     * will be correct, so we get the performance benefit.
+     */
+    public static int guessLength(char[] input, int start, int length) {
+        return guessLength(input, start, length, StringUtil.getCharArrayAccessor());
     }
 
-    public static int guessLength(byte[] chars, int start, int length) {
+    /**
+     * computes the length of binary data speculatively.
+     * Our requirement is to create byte[] of the exact length to store the binary data.
+     * If we do this in a straight-forward way, it takes two passes over the data.
+     * Experiments show that this is a non-trivial overhead (35% or so is spent on
+     * the first pass in calculating the length.)
+     * So the approach here is that we compute the length speculatively, without looking
+     * at the whole contents. The obtained speculative value is never less than the
+     * actual length of the binary data, but it may be bigger. So if the speculation
+     * goes wrong, we'll pay the cost of reallocation and buffer copying.
+     * If the base64 text is tightly packed with no indentation nor illegal char
+     * (like what most web services produce), then the speculation of this method
+     * will be correct, so we get the performance benefit.
+     */
+    public static int guessLength(CharSequence input, int start, int length) {
+        return guessLength(input, start, length, StringUtil.getCharSequenceAccessor());
+    }
 
+    /**
+     * computes the length of binary data speculatively.
+     * Our requirement is to create byte[] of the exact length to store the binary data.
+     * If we do this in a straight-forward way, it takes two passes over the data.
+     * Experiments show that this is a non-trivial overhead (35% or so is spent on
+     * the first pass in calculating the length.)
+     * So the approach here is that we compute the length speculatively, without looking
+     * at the whole contents. The obtained speculative value is never less than the
+     * actual length of the binary data, but it may be bigger. So if the speculation
+     * goes wrong, we'll pay the cost of reallocation and buffer copying.
+     * If the base64 text is tightly packed with no indentation nor illegal char
+     * (like what most web services produce), then the speculation of this method
+     * will be correct, so we get the performance benefit.
+     */
+    private static <T> int guessLength(T input, int start, int length, StringUtil.ICharAccessor<T> charAtFunction) {
         // compute the tail '=' chars
         int j = length - 1;
         for (; j >= 0; j--) {
-            byte code = DECODE_MAP[chars[start + j]];
+            char ch = charAtFunction.charAt(input, start + j);
+            byte code = DECODE_MAP[ch];
             if (code == PADDING) {
                 continue;
             }
@@ -208,24 +246,47 @@ public class Base64Parser {
      * @param length
      */
     public void generatePureByteArrayFromBase64String(byte[] input, int start, int length) {
-        // The base64 character length equals to utf8length
-        if (length % 4 != 0) {
-            throw new IllegalArgumentException(
-                    "Invalid Base64 string, the length of the string should be a multiple of 4");
-        }
-        final int buflen = guessLength(input, start, length);
-        ensureCapacity(buflen);
-        this.length = parseBase64String(input, start, length, storage, 0);
+        generatePureByteArrayFromBase64String(input, start, length, StringUtil.getByteArrayAsCharAccessor());
     }
 
+    /**
+     * Same as {@link #parseBase64String(char[], int, int, byte[], int)}, but we will provide the storage for caller
+     *
+     * @param input
+     * @param start
+     * @param length
+     */
     public void generatePureByteArrayFromBase64String(char[] input, int start, int length) {
+        generatePureByteArrayFromBase64String(input, start, length, StringUtil.getCharArrayAccessor());
+    }
+
+    /**
+     * Same as {@link #parseBase64String(CharSequence, int, int, byte[], int)}, but we will provide the storage for caller
+     *
+     * @param input
+     * @param start
+     * @param length
+     */
+    public void generatePureByteArrayFromBase64String(CharSequence input, int start, int length) {
+        generatePureByteArrayFromBase64String(input, start, length, StringUtil.getCharSequenceAccessor());
+    }
+
+    /**
+     * Same as {@link #parseBase64String(Object, int, int, StringUtil.ICharAccessor, byte[], int)}, but we will provide the storage for caller
+     *
+     * @param input
+     * @param start
+     * @param length
+     */
+    private <T> void generatePureByteArrayFromBase64String(T input, int start, int length,
+            StringUtil.ICharAccessor<T> charAtFunction) {
         if (length % 4 != 0) {
             throw new IllegalArgumentException(
                     "Invalid Base64 string, the length of the string should be a multiple of 4");
         }
-        final int buflen = guessLength(input, start, length);
+        final int buflen = guessLength(input, start, length, charAtFunction);
         ensureCapacity(buflen);
-        this.length = parseBase64String(input, start, length, storage, 0);
+        this.length = parseBase64String(input, start, length, charAtFunction, storage, 0);
     }
 
     private void ensureCapacity(int length) {
@@ -246,5 +307,4 @@ public class Base64Parser {
         }
         return outLength;
     }
-
 }
diff --git a/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/bytes/HexParser.java b/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/bytes/HexParser.java
index 46bc0a4..260e99f 100644
--- a/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/bytes/HexParser.java
+++ b/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/bytes/HexParser.java
@@ -79,15 +79,17 @@ public class HexParser {
 
     public static void generateByteArrayFromHexString(char[] input, int start, int length, byte[] output, int offset) {
         for (int i = 0; i < length; i += 2) {
-            output[offset + i / 2] = (byte) ((getValueFromValidHexChar(input[start + i]) << 4)
-                    + getValueFromValidHexChar(input[start + i + 1]));
+            output[offset + i / 2] = getByteFromValidHexChars(input[start + i], input[start + i + 1]);
         }
     }
 
     public static void generateByteArrayFromHexString(byte[] input, int start, int length, byte[] output, int offset) {
         for (int i = 0; i < length; i += 2) {
-            output[offset + i / 2] = (byte) ((getValueFromValidHexChar((char) input[start + i]) << 4)
-                    + getValueFromValidHexChar((char) input[start + i + 1]));
+            output[offset + i / 2] = getByteFromValidHexChars((char) input[start + i], (char) input[start + i + 1]);
         }
     }
+
+    public static byte getByteFromValidHexChars(char c0, char c1) {
+        return (byte) ((getValueFromValidHexChar(c0) << 4) + getValueFromValidHexChar(c1));
+    }
 }
diff --git a/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/bytes/HexPrinter.java b/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/bytes/HexPrinter.java
index d340526..f143e9f 100644
--- a/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/bytes/HexPrinter.java
+++ b/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/bytes/HexPrinter.java
@@ -37,12 +37,14 @@ public class HexPrinter {
         return (byte) (i < 10 ? i + '0' : i + (c.a - 10));
     }
 
-    public static Appendable printHexString(byte[] bytes, int start, int length, Appendable appendable)
-            throws IOException {
+    public static void printHexString(byte[] bytes, int start, int length, Appendable appendable) throws IOException {
         for (int i = 0; i < length; ++i) {
-            appendable.append((char) hex((bytes[start + i] >>> 4) & 0x0f, Case.UPPER_CASE));
-            appendable.append((char) hex((bytes[start + i] & 0x0f), Case.UPPER_CASE));
+            printByte(bytes[start + i], appendable);
         }
-        return appendable;
+    }
+
+    public static void printByte(byte b, Appendable appendable) throws IOException {
+        appendable.append((char) hex((b >>> 4) & 0x0f, Case.UPPER_CASE));
+        appendable.append((char) hex((b & 0x0f), Case.UPPER_CASE));
     }
 }