From ee57e93e580dd4a595cf1098a4f35febfbc6a990 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?z=C5=8Dng=20y=C7=94?= Date: Wed, 15 May 2019 16:52:09 +0800 Subject: [PATCH] feat: support custom decode handler (#119) --- .autod.conf.js | 4 +- index.js | 5 ++ lib/custom_handler.js | 28 +++++++++++ lib/v1/decoder.js | 3 +- lib/v2/decoder.js | 9 ++-- package.json | 18 +++---- test/custom_handler.test.js | 97 +++++++++++++++++++++++++++++++++++++ 7 files changed, 149 insertions(+), 15 deletions(-) create mode 100644 lib/custom_handler.js create mode 100644 test/custom_handler.test.js diff --git a/.autod.conf.js b/.autod.conf.js index 939d652..23fa1bf 100644 --- a/.autod.conf.js +++ b/.autod.conf.js @@ -13,6 +13,8 @@ module.exports = { 'istanbul', ], semver: [ + 'byte@1', + 'debug@3', 'mocha@3', ], -}; \ No newline at end of file +}; diff --git a/index.js b/index.js index 00b3cea..1600a65 100644 --- a/index.js +++ b/index.js @@ -46,3 +46,8 @@ exports.encode = function encode(obj, version) { encoder.reset(); return encoder.write(obj).get(); }; + +var custom = require('./lib/custom_handler'); + +exports.registerDecodeHandler = custom.registerDecodeHandler; +exports.deregisterDecodeHandler= custom.deregisterDecodeHandler; diff --git a/lib/custom_handler.js b/lib/custom_handler.js new file mode 100644 index 0000000..5125bb6 --- /dev/null +++ b/lib/custom_handler.js @@ -0,0 +1,28 @@ +'use strict'; + +var assert = require('assert'); + +var handlers = {}; + +function deregisterDecodeHandler(className) { + delete handlers[className]; +} + +function registerDecodeHandler(className, handler) { + assert(typeof handler === 'function', 'handler should be a function'); + handlers[className] = handler; +} + +function handle(result, withType) { + var className = result.$class; + var handler = handlers[className]; + + if (handler) { + result = handler(result); + } + return withType ? result : result.$; +} + +exports.handle = handle; +exports.registerDecodeHandler = registerDecodeHandler; +exports.deregisterDecodeHandler = deregisterDecodeHandler; diff --git a/lib/v1/decoder.js b/lib/v1/decoder.js index c71bd9e..eed5e73 100644 --- a/lib/v1/decoder.js +++ b/lib/v1/decoder.js @@ -5,6 +5,7 @@ var ByteBuffer = require('byte'); var is = require('is-type-of'); var utils = require('../utils'); var object = require('../object'); +var handle = require('../custom_handler').handle; var JavaExceptionError = object.JavaExceptionError; var supportES6Map = require('../utils').supportES6Map; @@ -417,7 +418,7 @@ proto.readObject = function (withType) { result.$ = new JavaExceptionError(result, withType); } - return withType ? result : result.$; + return handle(result, withType); }; utils.addByteCodes(BYTE_CODES, [ diff --git a/lib/v2/decoder.js b/lib/v2/decoder.js index a406095..4279667 100644 --- a/lib/v2/decoder.js +++ b/lib/v2/decoder.js @@ -5,6 +5,7 @@ var is = require('is-type-of'); var debug = require('debug')('hessian:v2:decoder'); var DecoderV1 = require('../v1/decoder'); var utils = require('../utils'); +var handle = require('../custom_handler').handle; var JavaExceptionError = require('../object').JavaExceptionError; var supportES6Map = require('../utils').supportES6Map; @@ -612,7 +613,7 @@ proto.readObject = function (withType) { result.$ = new JavaExceptionError(result, withType); } - return withType ? result : result.$; + return handle(result, withType); }; utils.addByteCodes(BYTE_CODES, [ @@ -777,7 +778,7 @@ proto.readHashMap = function (withType) { var result = {}; this._addRef(result); this._readMap(result, withType); - return result; + return handle({ $class: 'java.util.HashMap', $: result }, withType); }; utils.addByteCodes(BYTE_CODES, [ @@ -820,7 +821,7 @@ proto.readMap = function (withType) { var map = {}; this._addRef(map); this._readMap(map); - return map; + return handle({ $class: 'java.util.HashMap', $: map }, withType); } var result = { @@ -836,7 +837,7 @@ proto.readMap = function (withType) { result.$ = new JavaExceptionError(result); } - return withType ? result : result.$; + return handle(result, withType); }; utils.addByteCodes(BYTE_CODES, [ diff --git a/package.json b/package.json index 30b8788..6144856 100644 --- a/package.json +++ b/package.json @@ -34,20 +34,20 @@ }, "homepage": "https://github.com/node-modules/hessian.js", "dependencies": { - "byte": "^1.3.0", - "debug": "^3.1.0", - "is-type-of": "^1.2.0", - "long": "^3.2.0", - "utility": "^1.13.1" + "byte": "^1.4.1", + "debug": "^3.2.6", + "is-type-of": "^1.2.1", + "long": "^4.0.0", + "utility": "^1.16.1" }, "devDependencies": { - "autod": "^3.0.1", + "autod": "^3.1.0", "beautify-benchmark": "^0.2.4", "benchmark": "^2.1.4", "istanbul": "^0.4.5", - "js-to-java": "^2.4.0", - "jshint": "^2.9.5", - "mm": "^2.2.0", + "js-to-java": "^2.6.1", + "jshint": "^2.10.2", + "mm": "^2.5.0", "mocha": "^3.5.3" }, "engines": { diff --git a/test/custom_handler.test.js b/test/custom_handler.test.js new file mode 100644 index 0000000..0f21cf1 --- /dev/null +++ b/test/custom_handler.test.js @@ -0,0 +1,97 @@ +'use strict'; + +var assert = require('assert'); +var hessian = require('../'); +var supportES6Map = require('../lib/utils').supportES6Map; + +describe('utils.test.js', function () { + describe('v1.0', function () { + it('should decode with custom handler', function () { + hessian.registerDecodeHandler('java.math.BigDecimal', function (result) { + return { + $class: result.$class, + $: result.$.value, + }; + }); + var o = { $class: 'java.math.BigDecimal', $: { value: '100.06' } }; + var buf = hessian.encode(o, '1.0'); + var output = hessian.decode(buf, '1.0'); + assert(output === '100.06'); + hessian.deregisterDecodeHandler('java.math.BigDecimal'); + output = hessian.decode(buf, '1.0'); + assert.deepEqual(output, { value: '100.06' }); + }); + + if (!supportES6Map) { + return; + } + + it('should decode map with custom handler', function () { + hessian.registerDecodeHandler('java.util.HashMap', function (result) { + return { + $class: result.$class, + $: result.$.$map, + }; + }); + var map = new Map(); + map.set(1, 'fee'); + map.set(2, 'fie'); + map.set(3, 'foe'); + var buf = hessian.encode({ + $class: 'java.util.HashMap', + $: map + }, '1.0'); + var output = hessian.decode(buf, '1.0'); + assert(output instanceof Map); + assert(output.get(1) === 'fee'); + assert(output.get(2) === 'fie'); + assert(output.get(3) === 'foe'); + hessian.deregisterDecodeHandler('java.util.HashMap'); + }); + }); + + describe('v2.0', function () { + it('should decode with custom handler', function () { + hessian.registerDecodeHandler('java.math.BigDecimal', function (result) { + return { + $class: result.$class, + $: result.$.value, + }; + }); + var o = { $class: 'java.math.BigDecimal', $: { value: '100.06' } }; + var buf = hessian.encode(o, '2.0'); + var output = hessian.decode(buf, '2.0'); + assert(output === '100.06'); + hessian.deregisterDecodeHandler('java.math.BigDecimal'); + output = hessian.decode(buf, '2.0'); + assert.deepEqual(output, { value: '100.06' }); + }); + + if (!supportES6Map) { + return; + } + + it('should decode map with custom handler', function () { + hessian.registerDecodeHandler('java.util.HashMap', function (result) { + return { + $class: result.$class, + $: result.$.$map, + }; + }); + var map = new Map(); + map.set(1, 'fee'); + map.set(2, 'fie'); + map.set(3, 'foe'); + var buf = hessian.encode({ + $class: 'java.util.HashMap', + $: map + }, '2.0'); + var output = hessian.decode(buf, '2.0'); + assert(output instanceof Map); + assert(output.get(1) === 'fee'); + assert(output.get(2) === 'fie'); + assert(output.get(3) === 'foe'); + hessian.deregisterDecodeHandler('java.util.HashMap'); + }); + }); +});