embulk-filter-base64 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 920673effb3067f179e366a12a6b1ea760a9c199
4
- data.tar.gz: a77a241890b994b2fabc95d1ae175f314f70f6ce
3
+ metadata.gz: 076a19622912f88e9f4c0446a5ff1b656de12cad
4
+ data.tar.gz: 62fe25a76158dfacafc3af6b57b34bb76cd1f34c
5
5
  SHA512:
6
- metadata.gz: 85586eecb14aeba081c8706353c393c11d7b3592b1ef3d3f3a5a90bcd8bce8268adaad14c044c35cab95a2da1c94eb6ebdadfb899ffcb2d982a7e287ef635e80
7
- data.tar.gz: db625af1af9e2ba4a3b4f38de4c23d5f1f48276be36b45b89edd0408b6eb7cc69f7f88f699edc96f373baa66ec06a0bc283f23cb9fd36b53fa8832bc67e31d3c
6
+ metadata.gz: 04e9a03179c8c906dda682eaa3db724a83fbf321f9559f0de6dd1797518ddc9be7382a0440e43c93ec440d574c79c23a3c1927e82b4e18d49a82162a26eb749c
7
+ data.tar.gz: a6b749e4f88042449bd4e0ee3b8cfa2fbfd937fe5a2370a6f10f833b818fa4a2305c7e0d811344010685b45d0171fde3e3707cc659c1f7ee7dc306bcd79ed877
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Base64 filter plugin for Embulk
2
2
 
3
- An Embulk filter plugin to encode/decode string by Base64.
3
+ An Embulk filter plugin to encode/decode string by Base64, Base32 and Base16.
4
4
 
5
5
  ## Overview
6
6
 
@@ -8,23 +8,21 @@ An Embulk filter plugin to encode/decode string by Base64.
8
8
 
9
9
  ## Configuration
10
10
 
11
- * columns: Input columns to encode/decode (array of hash, required)
11
+ * **columns**: Input columns to encode/decode (array of hash, required)
12
12
  - **name**
13
13
  + name of input column (string, required)
14
14
  - **decode**, **encode**
15
15
  + whether to encode or decode the value (boolean, default: `false`)
16
- + either one must be `true` and exception is thrown if both are `true` or both are `false`
17
-
18
- ## Limitation
19
-
20
- * Java8 environment is needed because this plugin uses [java.util.Base64](https://docs.oracle.com/javase/8/docs/api/java/util/Base64.html) of Java8
21
- * Type of input value to be encoded must be string.
22
- - encoded value is string and is is needed to align the type of input and output value
23
- + e.g. 1234(string) is encoded into MTIzNA==(string)
24
- * Type of output decoded value is also string
25
- - this plugin does nothing like type casting
26
- + e.g. MTIzNA==(string) is decoded into 1234(string)
27
- - if you want type casting, use [embulk-filter-typecast](https://github.com/sonots/embulk-filter-typecast)
16
+ + either one must be `true` and exception is thrown when both are `true` or both are `false`
17
+ - **encording**
18
+ + encording type (string, default: 'Base64')
19
+ + must be one of the follwing, Base64, Base32, Base16
20
+ - **urlsafe**
21
+ + whether to use urlsafe character in encoded string
22
+ + works only when `encording: Base64`
23
+ - **hex**
24
+ + whether to maintain sort order of encoded string
25
+ + works only when `encording: Base32`
28
26
 
29
27
  ## Example
30
28
 
@@ -32,79 +30,53 @@ An Embulk filter plugin to encode/decode string by Base64.
32
30
 
33
31
  See [example_encode.yml](./example/example_encode.yml) and [example_encode.csv](./example/example_encode.csv).
34
32
 
33
+ input:
34
+
35
+ ```csv
36
+ 100,A0?B1>,A0?B1>,A0?B1>,A0?B1>,A0?B1>
37
+ 101,ab?cd~,ab?cd~,ab?cd~,ab?cd~,ab?cd~
38
+ ```
39
+
40
+ output:
41
+
35
42
  ```bash
36
- $ embulk preview -G example/example_encode.yml
37
- *************************** 1 ***************************
38
- id ( long) : 10
39
- string to encode (string) : Sm9obg==
40
- long to encode (string) : MTIzNDU2
41
- double to encode (string) : MzYuMjg=
42
- boolean to encode (string) : dHJ1ZQ==
43
- timestamp to encode (string) : MjAxNi0xMi0zMSAyMzo1OTo1OQ==
44
- json to encode (string) : eyJhZ2UiOiAyM30=
45
- *************************** 2 ***************************
46
- id ( long) : 11
47
- string to encode (string) : RGF2aWQ=
48
- long to encode (string) : MjM0NTY3
49
- double to encode (string) : MTI1LjE=
50
- boolean to encode (string) : ZmFsc2U=
51
- timestamp to encode (string) : MjAxNy0wMS0wMSAwMDowMDowMA==
52
- json to encode (string) : eyJhZ2UiOiAzNH0=
43
+ $ embulk preview example/example_encode.yml
44
+ +---------+---------------+------------------+------------------+------------------+---------------+
45
+ | id:long | Base64:string | Base64Url:string | Base32:string | Base32Hex:string | Base16:string |
46
+ +---------+---------------+------------------+------------------+------------------+---------------+
47
+ | 100 | QTA/QjE+ | QTA_QjE- | IEYD6QRRHY====== | 84O3UGHH7O====== | 41303F42313E |
48
+ | 101 | YWI/Y2R+ | YWI_Y2R- | MFRD6Y3EPY====== | C5H3UOR4FO====== | 61623F63647E |
49
+ +---------+---------------+------------------+------------------+------------------+---------------+
53
50
  ```
54
51
 
55
52
  ### decode
56
53
 
57
54
  See [example_decode.yml](./example/example_decode.yml) and [example_decode.csv](./example/example_decode.csv).
58
55
 
59
- ```bash
60
- $ embulk preview -G example/example_decode.yml
61
- *************************** 1 ***************************
62
- id ( long) : 10
63
- string to decode (string) : John
64
- long to decode (string) : 123456
65
- double to decode (string) : 36.28
66
- boolean to decode (string) : true
67
- timestamp to decode (string) : 2016-12-31 23:59:59
68
- json to decode (string) : {"age": 23}
69
- *************************** 2 ***************************
70
- id ( long) : 11
71
- string to decode (string) : David
72
- long to decode (string) : 234567
73
- double to decode (string) : 125.01
74
- boolean to decode (string) : false
75
- timestamp to decode (string) : 2017-01-01 00:00:00
76
- json to decode (string) : {"age": 34}
77
- ```
56
+ input:
78
57
 
79
- ### decode and cast type
58
+ ```csv
59
+ 100,QTA/QjE+,QTA_QjE-,IEYD6QRRHY======,84O3UGHH7O======,41303F42313E
60
+ 101,YWI/Y2R+,YWI_Y2R-,MFRD6Y3EPY======,C5H3UOR4FO======,61623F63647E
61
+ ```
80
62
 
81
- See [example_decode_with_typecast.yml](./example/example_decode_with_typecast.yml) and [example_decode.csv](./example/example_decode.csv).
63
+ output:
82
64
 
83
65
  ```bash
84
- $ embulk preview -G example/example_decode_with_typecast.yml
85
- *************************** 1 ***************************
86
- id ( long) : 10
87
- string to decode ( string) : John
88
- long to decode ( long) : 123,456
89
- double to decode ( double) : 36.28
90
- boolean to decode ( boolean) : true
91
- timestamp to decode (timestamp) : 2016-12-31 23:59:00.590 UTC
92
- json to decode ( json) : {"age":23}
93
- *************************** 2 ***************************
94
- id ( long) : 11
95
- string to decode ( string) : David
96
- long to decode ( long) : 234,567
97
- double to decode ( double) : 125.01
98
- boolean to decode ( boolean) : false
99
- timestamp to decode (timestamp) : 2017-01-01 00:00:00 UTC
100
- json to decode ( json) : {"age":34}
66
+ $ embulk preview example/example_decode.yml
67
+ +---------+---------------+------------------+---------------+------------------+---------------+
68
+ | id:long | Base64:string | Base64Url:string | Base32:string | Base32Hex:string | Base16:string |
69
+ +---------+---------------+------------------+---------------+------------------+---------------+
70
+ | 100 | A0?B1> | A0?B1> | A0?B1> | A0?B1> | A0?B1> |
71
+ | 101 | ab?cd~ | ab?cd~ | ab?cd~ | ab?cd~ | ab?cd~ |
72
+ +---------+---------------+------------------+---------------+------------------+---------------+
101
73
  ```
102
74
 
75
+ ## Limitation
103
76
 
104
- ### Todo
105
-
106
- * [Support base64 in apache commons codec](https://github.com/ysk24ok/embulk-filter-base64/issues/1)
107
- * [Support encoder/decoder of URL and MIME](https://github.com/ysk24ok/embulk-filter-base64/issues/2)
77
+ * Type of input value to be encoded must be string.
78
+ * Type of decoded output value will be string
79
+ - if you want type casting, use [embulk-filter-typecast](https://github.com/sonots/embulk-filter-typecast)
108
80
 
109
81
  ## Build
110
82
 
@@ -13,7 +13,7 @@ configurations {
13
13
  provided
14
14
  }
15
15
 
16
- version = "0.1.1"
16
+ version = "0.2.0"
17
17
 
18
18
  sourceCompatibility = 1.7
19
19
  targetCompatibility = 1.7
@@ -23,6 +23,7 @@ dependencies {
23
23
  provided "org.embulk:embulk-core:0.8.15"
24
24
  // compile "YOUR_JAR_DEPENDENCY_GROUP:YOUR_JAR_DEPENDENCY_MODULE:YOUR_JAR_DEPENDENCY_VERSION"
25
25
  testCompile "junit:junit:4.+"
26
+ testCompile "org.hamcrest:hamcrest-library:1.+"
26
27
  testCompile "org.embulk:embulk-core:0.8.15:tests"
27
28
  }
28
29
 
@@ -76,7 +77,7 @@ Gem::Specification.new do |spec|
76
77
  spec.version = "${project.version}"
77
78
  spec.authors = ["Yusuke NISHIOKA"]
78
79
  spec.summary = %[Base64 filter plugin for Embulk]
79
- spec.description = %[An Embulk filter plugin to encode/decode string by Base64.]
80
+ spec.description = %[An Embulk filter plugin to encode/decode string by Base64, Base32 and Base16.]
80
81
  spec.email = ["yusuke.nishioka.0713@gmail.com"]
81
82
  spec.licenses = ["MIT"]
82
83
  spec.homepage = "https://github.com/ysk24ok/embulk-filter-base64"
@@ -1,2 +1,2 @@
1
- 10,Sm9obg==,MTIzNDU2,MzYuMjg=,dHJ1ZQ==,MjAxNi0xMi0zMSAyMzo1OTo1OQ==,eyJhZ2UiOiAyM30=
2
- 11,RGF2aWQ=,MjM0NTY3,MTI1LjAx,ZmFsc2U=,MjAxNy0wMS0wMSAwMDowMDowMA==,eyJhZ2UiOiAzNH0=
1
+ 100,QTA/QjE+,QTA_QjE-,IEYD6QRRHY======,84O3UGHH7O======,41303F42313E
2
+ 101,YWI/Y2R+,YWI_Y2R-,MFRD6Y3EPY======,C5H3UOR4FO======,61623F63647E
@@ -4,21 +4,19 @@ in:
4
4
  parser:
5
5
  type: csv
6
6
  columns:
7
- - {name: id, type: long}
8
- - {name: string to decode, type: string}
9
- - {name: long to decode, type: string}
10
- - {name: double to decode, type: string}
11
- - {name: boolean to decode, type: string}
12
- - {name: timestamp to decode, type: string}
13
- - {name: json to decode, type: string}
7
+ - {name: id, type: long}
8
+ - {name: Base64, type: string}
9
+ - {name: Base64Url, type: string}
10
+ - {name: Base32, type: string}
11
+ - {name: Base32Hex, type: string}
12
+ - {name: Base16, type: string}
14
13
  filters:
15
14
  - type: base64
16
15
  columns:
17
- - {name: string to decode, decode: true}
18
- - {name: long to decode, decode: true}
19
- - {name: double to decode, decode: true}
20
- - {name: boolean to decode, decode: true}
21
- - {name: timestamp to decode, decode: true}
22
- - {name: json to decode, decode: true}
16
+ - {name: Base64, decode: true}
17
+ - {name: Base64Url, decode: true, urlsafe: true}
18
+ - {name: Base32, decode: true, encoding: Base32}
19
+ - {name: Base32Hex, decode: true, encoding: Base32, hex: true}
20
+ - {name: Base16, decode: true, encoding: Base16}
23
21
  out:
24
22
  type: stdout
@@ -1,2 +1,2 @@
1
- 10,John,123456,36.28,true,2016-12-31 23:59:59,{"age": 23}
2
- 11,David,234567,125.1,false,2017-01-01 00:00:00,{"age": 34}
1
+ 100,A0?B1>,A0?B1>,A0?B1>,A0?B1>,A0?B1>
2
+ 101,ab?cd~,ab?cd~,ab?cd~,ab?cd~,ab?cd~
@@ -4,21 +4,19 @@ in:
4
4
  parser:
5
5
  type: csv
6
6
  columns:
7
- - {name: id, type: long}
8
- - {name: string to encode, type: string}
9
- - {name: long to encode, type: string}
10
- - {name: double to encode, type: string}
11
- - {name: boolean to encode, type: string}
12
- - {name: timestamp to encode, type: string}
13
- - {name: json to encode, type: string}
7
+ - {name: id, type: long}
8
+ - {name: Base64, type: string}
9
+ - {name: Base64Url, type: string}
10
+ - {name: Base32, type: string}
11
+ - {name: Base32Hex, type: string}
12
+ - {name: Base16, type: string}
14
13
  filters:
15
14
  - type: base64
16
15
  columns:
17
- - {name: string to encode, encode: true}
18
- - {name: long to encode, encode: true}
19
- - {name: double to encode, encode: true}
20
- - {name: boolean to encode, encode: true}
21
- - {name: timestamp to encode, encode: true}
22
- - {name: json to encode, encode: true}
16
+ - {name: Base64, encode: true}
17
+ - {name: Base64Url, encode: true, urlsafe: true}
18
+ - {name: Base32, encode: true, encoding: Base32}
19
+ - {name: Base32Hex, encode: true, encoding: Base32, hex: true}
20
+ - {name: Base16, encode: true, encoding: Base16}
23
21
  out:
24
22
  type: stdout
@@ -0,0 +1,100 @@
1
+ package org.embulk.filter.base64;
2
+
3
+ import com.google.common.io.BaseEncoding;
4
+
5
+ import org.embulk.filter.base64.Base64FilterPlugin.ColumnTask;
6
+ import org.embulk.filter.base64.Base64FilterPlugin.PluginTask;
7
+ import org.embulk.spi.Column;
8
+
9
+ import java.util.HashMap;
10
+ import java.util.List;
11
+ import java.util.Map;
12
+ import java.util.Objects;
13
+
14
+ public class Base64Filter
15
+ {
16
+ private PluginTask task;
17
+ private final Map<String, ColumnTask> columnTaskMap;
18
+
19
+ Base64Filter(PluginTask task)
20
+ {
21
+ this.task = task;
22
+ this.columnTaskMap = getColumnTaskMap(task.getColumns());
23
+ }
24
+
25
+ private Map<String, ColumnTask> getColumnTaskMap(
26
+ List<ColumnTask> columnTasks)
27
+ {
28
+ Map<String, ColumnTask> m = new HashMap<>();
29
+ for (ColumnTask columnTask : columnTasks) {
30
+ m.put(columnTask.getName(), columnTask);
31
+ }
32
+ return m;
33
+ }
34
+
35
+ private ColumnTask getTask(Column column)
36
+ {
37
+ String colName = column.getName();
38
+ return columnTaskMap.get(colName);
39
+ }
40
+
41
+ public String doFilter(Column column, String inputValue)
42
+ {
43
+ ColumnTask colTask = getTask(column);
44
+ if (colTask == null) {
45
+ return inputValue;
46
+ }
47
+ String encoding = colTask.getEncoding();
48
+ boolean doEncode = colTask.getDoEncode().get();
49
+ boolean doDecode = colTask.getDoDecode().get();
50
+ // encode
51
+ if (doEncode && ! doDecode) {
52
+ byte[] inputAsBytes = inputValue.getBytes();
53
+ String encoded = null;
54
+ if (Objects.equals(encoding, "Base64")) {
55
+ if (colTask.getDoUrlsafe().get()) {
56
+ encoded = BaseEncoding.base64Url().encode(inputAsBytes);
57
+ }
58
+ else {
59
+ encoded = BaseEncoding.base64().encode(inputAsBytes);
60
+ }
61
+ }
62
+ else if (Objects.equals(encoding, "Base32")) {
63
+ if (colTask.getUseHex().get()) {
64
+ encoded = BaseEncoding.base32Hex().encode(inputAsBytes);
65
+ }
66
+ else {
67
+ encoded = BaseEncoding.base32().encode(inputAsBytes);
68
+ }
69
+ }
70
+ else if (Objects.equals(encoding, "Base16")) {
71
+ encoded = BaseEncoding.base16().encode(inputAsBytes);
72
+ }
73
+ return encoded;
74
+ }
75
+ // decode
76
+ else {
77
+ byte[] decodedAsBytes = null;
78
+ if (Objects.equals(encoding, "Base64")) {
79
+ if (colTask.getDoUrlsafe().get()) {
80
+ decodedAsBytes = BaseEncoding.base64Url().decode(inputValue);
81
+ }
82
+ else {
83
+ decodedAsBytes = BaseEncoding.base64().decode(inputValue);
84
+ }
85
+ }
86
+ else if (Objects.equals(encoding, "Base32")) {
87
+ if (colTask.getUseHex().get()) {
88
+ decodedAsBytes = BaseEncoding.base32Hex().decode(inputValue);
89
+ }
90
+ else {
91
+ decodedAsBytes = BaseEncoding.base32().decode(inputValue);
92
+ }
93
+ }
94
+ else if (Objects.equals(encoding, "Base16")) {
95
+ decodedAsBytes = BaseEncoding.base16().decode(inputValue);
96
+ }
97
+ return new String(decodedAsBytes);
98
+ }
99
+ }
100
+ }
@@ -1,29 +1,27 @@
1
1
  package org.embulk.filter.base64;
2
2
 
3
- import java.util.List;
4
- import java.util.Map;
5
- import java.util.HashMap;
6
- import java.util.Base64;
7
-
8
3
  import com.google.common.base.Optional;
4
+
9
5
  import org.embulk.config.Config;
10
6
  import org.embulk.config.ConfigDefault;
7
+ import org.embulk.config.ConfigException;
11
8
  import org.embulk.config.ConfigSource;
12
9
  import org.embulk.config.Task;
13
10
  import org.embulk.config.TaskSource;
14
11
  import org.embulk.spi.Column;
15
- import org.embulk.spi.ColumnVisitor;
16
- import org.embulk.spi.DataException;
17
12
  import org.embulk.spi.Exec;
18
13
  import org.embulk.spi.FilterPlugin;
19
14
  import org.embulk.spi.Page;
20
15
  import org.embulk.spi.PageBuilder;
21
- import org.embulk.spi.PageReader;
22
16
  import org.embulk.spi.PageOutput;
17
+ import org.embulk.spi.PageReader;
23
18
  import org.embulk.spi.Schema;
24
19
  import org.embulk.spi.type.Type;
25
20
  import org.embulk.spi.type.Types;
26
21
 
22
+ import java.util.Arrays;
23
+ import java.util.List;
24
+
27
25
  public class Base64FilterPlugin
28
26
  implements FilterPlugin
29
27
  {
@@ -31,17 +29,15 @@ public class Base64FilterPlugin
31
29
  extends Task
32
30
  {
33
31
  @Config("columns")
34
- public List<Base64ColumnTask> getColumns();
32
+ public List<ColumnTask> getColumns();
35
33
  }
36
34
 
37
- public interface Base64ColumnTask
35
+ public interface ColumnTask
38
36
  extends Task
39
37
  {
40
38
  @Config("name")
41
39
  public String getName();
42
40
 
43
- // TODO: getType
44
-
45
41
  @Config("encode")
46
42
  @ConfigDefault("false")
47
43
  public Optional<Boolean> getDoEncode();
@@ -49,27 +45,46 @@ public class Base64FilterPlugin
49
45
  @Config("decode")
50
46
  @ConfigDefault("false")
51
47
  public Optional<Boolean> getDoDecode();
48
+
49
+ @Config("encoding")
50
+ @ConfigDefault("\"Base64\"")
51
+ public String getEncoding();
52
+
53
+ @Config("urlsafe")
54
+ @ConfigDefault("false")
55
+ public Optional<Boolean> getDoUrlsafe();
56
+
57
+ @Config("hex")
58
+ @ConfigDefault("false")
59
+ public Optional<Boolean> getUseHex();
52
60
  }
53
61
 
54
62
  public void validate(PluginTask pluginTask, Schema inputSchema)
55
63
  {
56
- for (Base64ColumnTask task : pluginTask.getColumns()) {
57
- // throws exception if the column name does not exist
58
- inputSchema.lookupColumn(task.getName());
64
+ for (ColumnTask task : pluginTask.getColumns()) {
65
+ // throws exception when the column does not exist
66
+ Column column = inputSchema.lookupColumn(task.getName());
67
+ // check 'encode: true' or 'decode: true' in ColumnTask
59
68
  boolean doEncode = task.getDoEncode().get();
60
69
  boolean doDecode = task.getDoDecode().get();
61
70
  boolean bothTrue = doEncode && doDecode;
62
71
  boolean bothFalse = !doEncode && !doDecode;
63
72
  if (bothTrue || bothFalse) {
64
73
  String errMsg = "Specify either 'encode: true' or 'decode: true'";
65
- throw new DataException(errMsg);
74
+ throw new ConfigException(errMsg);
66
75
  }
67
- }
68
- for (Column column : inputSchema.getColumns()) {
76
+ // check 'encoding' option in ColumnTask
77
+ String[] allowedEncordings = {"Base16", "Base32", "Base64"};
78
+ String encoding = task.getEncoding();
79
+ if (!Arrays.asList(allowedEncordings).contains(encoding)) {
80
+ String errMsg = "Encording must be one of the following: Base16, Base32, Base64";
81
+ throw new ConfigException(errMsg);
82
+ }
83
+ // check type of input cloumn
69
84
  Type colType = column.getType();
70
85
  if (!Types.STRING.equals(colType)) {
71
86
  String errMsg = "Type of input columns must be string";
72
- throw new DataException(errMsg);
87
+ throw new ConfigException(errMsg);
73
88
  }
74
89
  }
75
90
  }
@@ -92,8 +107,9 @@ public class Base64FilterPlugin
92
107
  PageBuilder pageBuilder = new PageBuilder(
93
108
  Exec.getBufferAllocator(), outputSchema, output);
94
109
  PageReader pageReader = new PageReader(inputSchema);
110
+ Base64Filter filter = new Base64Filter(task);
95
111
  ColumnVisitorImpl visitor = new ColumnVisitorImpl(
96
- task, pageReader, pageBuilder);
112
+ pageReader, pageBuilder, filter);
97
113
 
98
114
  return new PageOutputImpl(
99
115
  pageReader, pageBuilder, outputSchema, visitor);
@@ -1,68 +1,21 @@
1
1
  package org.embulk.filter.base64;
2
2
 
3
- import java.util.List;
4
- import java.util.Map;
5
- import java.util.HashMap;
6
- import java.util.Base64;
7
-
8
- import org.embulk.config.Config;
9
- import org.embulk.config.ConfigDefault;
10
- import org.embulk.config.Task;
11
3
  import org.embulk.spi.Column;
12
4
  import org.embulk.spi.ColumnVisitor;
13
- import org.embulk.spi.DataException;
14
5
  import org.embulk.spi.PageBuilder;
15
6
  import org.embulk.spi.PageReader;
16
- import org.embulk.spi.Schema;
17
-
18
- import org.embulk.filter.base64.Base64FilterPlugin.Base64ColumnTask;
19
- import org.embulk.filter.base64.Base64FilterPlugin.PluginTask;
20
7
 
21
- public class ColumnVisitorImpl
22
- implements ColumnVisitor
8
+ public class ColumnVisitorImpl implements ColumnVisitor
23
9
  {
24
10
  private final PageReader pageReader;
25
11
  private final PageBuilder pageBuilder;
26
- private final Map<String, Base64ColumnTask> base64ColumnMap;
12
+ private final Base64Filter filter;
27
13
 
28
- ColumnVisitorImpl(PluginTask task, PageReader reader, PageBuilder builder)
14
+ ColumnVisitorImpl(PageReader reader, PageBuilder builder, Base64Filter filter)
29
15
  {
30
16
  this.pageReader = reader;
31
17
  this.pageBuilder = builder;
32
- this.base64ColumnMap = getBase64ColumnMap(task.getColumns());
33
- }
34
-
35
- private static Map<String, Base64ColumnTask> getBase64ColumnMap(
36
- List<Base64ColumnTask> columnTasks)
37
- {
38
- Map<String, Base64ColumnTask> m = new HashMap<>();
39
- for (Base64ColumnTask columnTask : columnTasks) {
40
- m.put(columnTask.getName(), columnTask);
41
- }
42
- return m;
43
- }
44
-
45
- private Base64ColumnTask getTask(Column column)
46
- {
47
- String colName = column.getName();
48
- return base64ColumnMap.get(colName);
49
- }
50
-
51
- private String executeTask(Base64ColumnTask task, Column column)
52
- {
53
- boolean doEncode = task.getDoEncode().get();
54
- boolean doDecode = task.getDoDecode().get();
55
- // encode
56
- if (doEncode) {
57
- String raw = pageReader.getString(column);
58
- return Base64.getEncoder().encodeToString(raw.getBytes());
59
- }
60
- // decode
61
- //else if (doDecode) {
62
- else {
63
- String encoded = pageReader.getString(column);
64
- return new String(Base64.getDecoder().decode(encoded));
65
- }
18
+ this.filter = filter;
66
19
  }
67
20
 
68
21
  @Override
@@ -108,17 +61,9 @@ public class ColumnVisitorImpl
108
61
  pageBuilder.setNull(outputColumn);
109
62
  }
110
63
  else {
111
- Base64ColumnTask task = getTask(outputColumn);
112
- // when there is no task executed on this column
113
- if (task == null) {
114
- pageBuilder.setString(
115
- outputColumn, pageReader.getString(outputColumn));
116
- // when there is a task
117
- }
118
- else {
119
- String str = executeTask(task, outputColumn);
120
- pageBuilder.setString(outputColumn, str);
121
- }
64
+ String outputValue = filter.doFilter(
65
+ outputColumn, pageReader.getString(outputColumn));
66
+ pageBuilder.setString(outputColumn, outputValue);
122
67
  }
123
68
  }
124
69
 
@@ -1,14 +1,14 @@
1
1
  package org.embulk.filter.base64;
2
2
 
3
3
  import org.embulk.EmbulkTestRuntime;
4
+ import org.embulk.config.ConfigException;
4
5
  import org.embulk.config.ConfigLoader;
5
6
  import org.embulk.config.ConfigSource;
6
- import org.embulk.spi.DataException;
7
+ import org.embulk.filter.base64.Base64FilterPlugin.PluginTask;
7
8
  import org.embulk.spi.Exec;
8
9
  import org.embulk.spi.Schema;
9
10
  import org.embulk.spi.SchemaConfigException;
10
11
  import org.embulk.spi.type.Types;
11
- import org.embulk.filter.base64.Base64FilterPlugin.PluginTask;
12
12
 
13
13
  import org.junit.Rule;
14
14
  import org.junit.Test;
@@ -39,8 +39,8 @@ public class TestBase64FilterPlugin
39
39
  PluginTask task = taskFromYamlString(
40
40
  "type: base64",
41
41
  "columns:",
42
- " - {name: to encode, type: string, encode: true}",
43
- " - {name: to decode, type: string, decode: true}"
42
+ " - {name: to encode, encode: true}",
43
+ " - {name: to decode, decode: true}"
44
44
  );
45
45
  Schema inputSchema = Schema.builder()
46
46
  .add("to encode", Types.STRING)
@@ -48,13 +48,13 @@ public class TestBase64FilterPlugin
48
48
  plugin.validate(task, inputSchema);
49
49
  }
50
50
 
51
- @Test(expected = DataException.class)
51
+ @Test(expected = ConfigException.class)
52
52
  public void testValidate_bothSpecified()
53
53
  {
54
54
  PluginTask task = taskFromYamlString(
55
55
  "type: base64",
56
56
  "columns:",
57
- " - {name: to encode, type: string, encode: true, decode: true}"
57
+ " - {name: to encode, encode: true, decode: true}"
58
58
  );
59
59
  Schema inputSchema = Schema.builder()
60
60
  .add("to encode", Types.STRING)
@@ -62,13 +62,13 @@ public class TestBase64FilterPlugin
62
62
  plugin.validate(task, inputSchema);
63
63
  }
64
64
 
65
- @Test(expected = DataException.class)
65
+ @Test(expected = ConfigException.class)
66
66
  public void testValidate_bothNotSpecified()
67
67
  {
68
68
  PluginTask task = taskFromYamlString(
69
69
  "type: base64",
70
70
  "columns:",
71
- " - {name: to encode, type: string}"
71
+ " - {name: to encode}"
72
72
  );
73
73
  Schema inputSchema = Schema.builder()
74
74
  .add("to encode", Types.STRING)
@@ -76,13 +76,13 @@ public class TestBase64FilterPlugin
76
76
  plugin.validate(task, inputSchema);
77
77
  }
78
78
 
79
- @Test(expected = DataException.class)
79
+ @Test(expected = ConfigException.class)
80
80
  public void testValidate_invalidInputType()
81
81
  {
82
82
  PluginTask task = taskFromYamlString(
83
83
  "type: base64",
84
84
  "columns:",
85
- " - {name: to encode, type: string, type: double}"
85
+ " - {name: to encode, encode: true}"
86
86
  );
87
87
  Schema inputSchema = Schema.builder()
88
88
  .add("to encode", Types.DOUBLE)
@@ -1,11 +1,8 @@
1
1
  package org.embulk.filter.base64;
2
2
 
3
- import java.util.List;
4
-
5
3
  import org.embulk.EmbulkTestRuntime;
6
- import org.embulk.config.ConfigLoader;
7
- import org.embulk.config.ConfigSource;
8
- import org.embulk.spi.Exec;
4
+ import org.embulk.filter.base64.Base64FilterPlugin.PageOutputImpl;
5
+ import org.embulk.filter.base64.Base64FilterPlugin.PluginTask;
9
6
  import org.embulk.spi.Page;
10
7
  import org.embulk.spi.PageBuilder;
11
8
  import org.embulk.spi.PageOutput;
@@ -15,20 +12,37 @@ import org.embulk.spi.Schema;
15
12
  import org.embulk.spi.TestPageBuilderReader.MockPageOutput;
16
13
  import org.embulk.spi.type.Types;
17
14
  import org.embulk.spi.util.Pages;
18
- import org.embulk.filter.base64.Base64FilterPlugin.PluginTask;
19
- import org.embulk.filter.base64.Base64FilterPlugin.PageOutputImpl;
20
- import org.embulk.filter.base64.ColumnVisitorImpl;
21
- import static org.embulk.filter.base64.TestBase64FilterPlugin.taskFromYamlString;
22
15
 
16
+ import org.junit.Before;
23
17
  import org.junit.Rule;
24
18
  import org.junit.Test;
25
- import static org.junit.Assert.*;
19
+
20
+ import static org.embulk.filter.base64.TestBase64FilterPlugin.taskFromYamlString;
21
+ import static org.junit.Assert.assertEquals;
22
+
23
+ import java.util.List;
26
24
 
27
25
  public class TestColumnVisitorImpl
28
26
  {
29
27
  @Rule
30
28
  public EmbulkTestRuntime runtime = new EmbulkTestRuntime();
31
29
 
30
+ private Schema inputSchemaToEncode;
31
+ private Schema inputSchemaToDecode;
32
+
33
+ @Before
34
+ public void createResource()
35
+ {
36
+ inputSchemaToEncode = Schema.builder()
37
+ .add("id", Types.LONG)
38
+ .add("to encode", Types.STRING)
39
+ .build();
40
+ inputSchemaToDecode = Schema.builder()
41
+ .add("id", Types.LONG)
42
+ .add("to decode", Types.STRING)
43
+ .build();
44
+ }
45
+
32
46
  private List<Object[]> filter(PluginTask task, Schema inputSchema, Object... objects)
33
47
  {
34
48
  MockPageOutput output = new MockPageOutput();
@@ -36,8 +50,9 @@ public class TestColumnVisitorImpl
36
50
  PageBuilder pageBuilder = new PageBuilder(
37
51
  runtime.getBufferAllocator(), outputSchema, output);
38
52
  PageReader pageReader = new PageReader(inputSchema);
53
+ Base64Filter filter = new Base64Filter(task);
39
54
  ColumnVisitorImpl visitor = new ColumnVisitorImpl(
40
- task, pageReader, pageBuilder);
55
+ pageReader, pageBuilder, filter);
41
56
 
42
57
  List<Page> pages = PageTestUtils.buildPage(
43
58
  runtime.getBufferAllocator(), inputSchema, objects);
@@ -52,42 +67,270 @@ public class TestColumnVisitorImpl
52
67
  }
53
68
 
54
69
  @Test
55
- public void testExecuteTask_encode()
70
+ public void testExecuteTask_encodeByBase64()
56
71
  {
72
+ // implicit
57
73
  PluginTask task = taskFromYamlString(
58
74
  "type: base64",
59
75
  "columns:",
60
- " - {name: to encode, type: string, encode: true}"
76
+ " - {name: id}",
77
+ " - {name: to encode, encode: true}"
61
78
  );
62
- Schema inputSchema = Schema.builder()
63
- .add("to encode", Types.STRING)
64
- .build();
65
- List<Object[]> records = filter(task, inputSchema,
66
- "John",
67
- "David"
79
+ List<Object[]> records = filter(task, inputSchemaToEncode,
80
+ Long.valueOf(100), "A0?B1>",
81
+ Long.valueOf(101), "ab?cd~"
68
82
  );
69
83
  assertEquals(2, records.size());
70
- assertEquals("Sm9obg==", records.get(0)[0]);
71
- assertEquals("RGF2aWQ=", records.get(1)[0]);
84
+ assertEquals(Long.valueOf(100), records.get(0)[0]);
85
+ assertEquals("QTA/QjE+", records.get(0)[1]);
86
+ assertEquals(Long.valueOf(101), records.get(1)[0]);
87
+ assertEquals("YWI/Y2R+", records.get(1)[1]);
88
+ // explicit
89
+ task = taskFromYamlString(
90
+ "type: base64",
91
+ "columns:",
92
+ " - {name: id}",
93
+ " - {name: to encode, encode: true, encoding: Base64}"
94
+ );
95
+ records = filter(task, inputSchemaToEncode,
96
+ Long.valueOf(100), "A0?B1>",
97
+ Long.valueOf(101), "ab?cd~"
98
+ );
99
+ assertEquals(2, records.size());
100
+ assertEquals(Long.valueOf(100), records.get(0)[0]);
101
+ assertEquals("QTA/QjE+", records.get(0)[1]);
102
+ assertEquals(Long.valueOf(101), records.get(1)[0]);
103
+ assertEquals("YWI/Y2R+", records.get(1)[1]);
72
104
  }
73
105
 
74
106
  @Test
75
- public void testExecuteTask_decode()
107
+ public void testExecuteTask_encodeByBase64Url()
76
108
  {
109
+ // implicit
77
110
  PluginTask task = taskFromYamlString(
78
111
  "type: base64",
79
112
  "columns:",
80
- " - {name: to decode, type: string, decode: true}"
113
+ " - {name: id}",
114
+ " - {name: to encode, encode: true, urlsafe: true}"
81
115
  );
82
- Schema inputSchema = Schema.builder()
83
- .add("to decode", Types.STRING)
84
- .build();
85
- List<Object[]> records = filter(task, inputSchema,
86
- "Sm9obg==",
87
- "RGF2aWQ="
116
+ List<Object[]> records = filter(task, inputSchemaToEncode,
117
+ Long.valueOf(100), "A0?B1>",
118
+ Long.valueOf(101), "ab?cd~"
119
+ );
120
+ assertEquals(2, records.size());
121
+ assertEquals(Long.valueOf(100), records.get(0)[0]);
122
+ assertEquals("QTA_QjE-", records.get(0)[1]);
123
+ assertEquals(Long.valueOf(101), records.get(1)[0]);
124
+ assertEquals("YWI_Y2R-", records.get(1)[1]);
125
+ // explicit
126
+ task = taskFromYamlString(
127
+ "type: base64",
128
+ "columns:",
129
+ " - {name: id}",
130
+ " - {name: to encode, encode: true, encoding: Base64, urlsafe: true}"
131
+ );
132
+ records = filter(task, inputSchemaToEncode,
133
+ Long.valueOf(100), "A0?B1>",
134
+ Long.valueOf(101), "ab?cd~"
135
+ );
136
+ assertEquals(2, records.size());
137
+ assertEquals(Long.valueOf(100), records.get(0)[0]);
138
+ assertEquals("QTA_QjE-", records.get(0)[1]);
139
+ assertEquals(Long.valueOf(101), records.get(1)[0]);
140
+ assertEquals("YWI_Y2R-", records.get(1)[1]);
141
+ }
142
+
143
+ @Test
144
+ public void testExecuteTask_encodeByBase32()
145
+ {
146
+ PluginTask task = taskFromYamlString(
147
+ "type: base64",
148
+ "columns:",
149
+ " - {name: id}",
150
+ " - {name: to encode, encode: true, encoding: Base32}"
151
+ );
152
+ List<Object[]> records = filter(task, inputSchemaToEncode,
153
+ Long.valueOf(100), "A0?B1>",
154
+ Long.valueOf(101), "ab?cd~"
155
+ );
156
+ assertEquals(2, records.size());
157
+ assertEquals(Long.valueOf(100), records.get(0)[0]);
158
+ assertEquals("IEYD6QRRHY======", records.get(0)[1]);
159
+ assertEquals(Long.valueOf(101), records.get(1)[0]);
160
+ assertEquals("MFRD6Y3EPY======", records.get(1)[1]);
161
+ }
162
+
163
+ @Test
164
+ public void testExecuteTask_encodeByBase32Hex()
165
+ {
166
+ PluginTask task = taskFromYamlString(
167
+ "type: base64",
168
+ "columns:",
169
+ " - {name: id}",
170
+ " - {name: to encode, encode: true, encoding: Base32, hex: true}"
171
+ );
172
+ List<Object[]> records = filter(task, inputSchemaToEncode,
173
+ Long.valueOf(100), "A0?B1>",
174
+ Long.valueOf(101), "ab?cd~"
175
+ );
176
+ assertEquals(2, records.size());
177
+ assertEquals(Long.valueOf(100), records.get(0)[0]);
178
+ assertEquals("84O3UGHH7O======", records.get(0)[1]);
179
+ assertEquals(Long.valueOf(101), records.get(1)[0]);
180
+ assertEquals("C5H3UOR4FO======", records.get(1)[1]);
181
+ }
182
+
183
+ @Test
184
+ public void testExecuteTask_encodeByBase16()
185
+ {
186
+ PluginTask task = taskFromYamlString(
187
+ "type: base64",
188
+ "columns:",
189
+ " - {name: id}",
190
+ " - {name: to encode, encode: true, encoding: Base16}"
191
+ );
192
+ List<Object[]> records = filter(task, inputSchemaToEncode,
193
+ Long.valueOf(100), "A0?B1>",
194
+ Long.valueOf(101), "ab?cd~"
195
+ );
196
+ assertEquals(2, records.size());
197
+ assertEquals(Long.valueOf(100), records.get(0)[0]);
198
+ assertEquals("41303F42313E", records.get(0)[1]);
199
+ assertEquals(Long.valueOf(101), records.get(1)[0]);
200
+ assertEquals("61623F63647E", records.get(1)[1]);
201
+ }
202
+
203
+ @Test
204
+ public void testExecuteTask_decodeByBase64()
205
+ {
206
+ // implicit
207
+ PluginTask task = taskFromYamlString(
208
+ "type: base64",
209
+ "columns:",
210
+ " - {name: id}",
211
+ " - {name: to decode, decode: true}"
212
+ );
213
+ List<Object[]> records = filter(task, inputSchemaToDecode,
214
+ Long.valueOf(100), "QTA/QjE+",
215
+ Long.valueOf(101), "YWI/Y2R+"
216
+ );
217
+ assertEquals(2, records.size());
218
+ assertEquals(Long.valueOf(100), records.get(0)[0]);
219
+ assertEquals("A0?B1>", records.get(0)[1]);
220
+ assertEquals(Long.valueOf(101), records.get(1)[0]);
221
+ assertEquals("ab?cd~", records.get(1)[1]);
222
+ // explicit
223
+ task = taskFromYamlString(
224
+ "type: base64",
225
+ "columns:",
226
+ " - {name: id}",
227
+ " - {name: to decode, decode: true, encoding: Base64}"
228
+ );
229
+ records = filter(task, inputSchemaToDecode,
230
+ Long.valueOf(100), "QTA/QjE+",
231
+ Long.valueOf(101), "YWI/Y2R+"
232
+ );
233
+ assertEquals(2, records.size());
234
+ assertEquals(Long.valueOf(100), records.get(0)[0]);
235
+ assertEquals("A0?B1>", records.get(0)[1]);
236
+ assertEquals(Long.valueOf(101), records.get(1)[0]);
237
+ assertEquals("ab?cd~", records.get(1)[1]);
238
+ }
239
+
240
+ @Test
241
+ public void testExecuteTask_decodeByBase64Url()
242
+ {
243
+ // implicit
244
+ PluginTask task = taskFromYamlString(
245
+ "type: base64",
246
+ "columns:",
247
+ " - {name: id}",
248
+ " - {name: to decode, decode: true, urlsafe: true}"
249
+ );
250
+ List<Object[]> records = filter(task, inputSchemaToDecode,
251
+ Long.valueOf(100), "QTA_QjE-",
252
+ Long.valueOf(101), "YWI_Y2R-"
253
+ );
254
+ assertEquals(2, records.size());
255
+ assertEquals(Long.valueOf(100), records.get(0)[0]);
256
+ assertEquals("A0?B1>", records.get(0)[1]);
257
+ assertEquals(Long.valueOf(101), records.get(1)[0]);
258
+ assertEquals("ab?cd~", records.get(1)[1]);
259
+ // explicit
260
+ task = taskFromYamlString(
261
+ "type: base64",
262
+ "columns:",
263
+ " - {name: id}",
264
+ " - {name: to decode, decode: true, encoding: Base64, urlsafe: true}"
265
+ );
266
+ records = filter(task, inputSchemaToDecode,
267
+ Long.valueOf(100), "QTA_QjE-",
268
+ Long.valueOf(101), "YWI_Y2R-"
269
+ );
270
+ assertEquals(2, records.size());
271
+ assertEquals(Long.valueOf(100), records.get(0)[0]);
272
+ assertEquals("A0?B1>", records.get(0)[1]);
273
+ assertEquals(Long.valueOf(101), records.get(1)[0]);
274
+ assertEquals("ab?cd~", records.get(1)[1]);
275
+ }
276
+
277
+ @Test
278
+ public void testExecuteTask_decodeByBase32()
279
+ {
280
+ PluginTask task = taskFromYamlString(
281
+ "type: base64",
282
+ "columns:",
283
+ " - {name: id}",
284
+ " - {name: to decode, decode: true, encoding: Base32}"
285
+ );
286
+ List<Object[]> records = filter(task, inputSchemaToDecode,
287
+ Long.valueOf(100), "IEYD6QRRHY======",
288
+ Long.valueOf(101), "MFRD6Y3EPY======"
289
+ );
290
+ assertEquals(2, records.size());
291
+ assertEquals(Long.valueOf(100), records.get(0)[0]);
292
+ assertEquals("A0?B1>", records.get(0)[1]);
293
+ assertEquals(Long.valueOf(101), records.get(1)[0]);
294
+ assertEquals("ab?cd~", records.get(1)[1]);
295
+ }
296
+
297
+ @Test
298
+ public void testExecuteTask_decodeByBase32Hex()
299
+ {
300
+ PluginTask task = taskFromYamlString(
301
+ "type: base64",
302
+ "columns:",
303
+ " - {name: id}",
304
+ " - {name: to decode, decode: true, encoding: Base32, hex: true}"
305
+ );
306
+ List<Object[]> records = filter(task, inputSchemaToDecode,
307
+ Long.valueOf(100), "84O3UGHH7O======",
308
+ Long.valueOf(101), "C5H3UOR4FO======"
309
+ );
310
+ assertEquals(2, records.size());
311
+ assertEquals(Long.valueOf(100), records.get(0)[0]);
312
+ assertEquals("A0?B1>", records.get(0)[1]);
313
+ assertEquals(Long.valueOf(101), records.get(1)[0]);
314
+ assertEquals("ab?cd~", records.get(1)[1]);
315
+ }
316
+
317
+ @Test
318
+ public void testExecuteTask_decodeByBase16()
319
+ {
320
+ PluginTask task = taskFromYamlString(
321
+ "type: base64",
322
+ "columns:",
323
+ " - {name: id}",
324
+ " - {name: to decode, decode: true, encoding: Base16}"
325
+ );
326
+ List<Object[]> records = filter(task, inputSchemaToDecode,
327
+ Long.valueOf(100), "41303F42313E",
328
+ Long.valueOf(101), "61623F63647E"
88
329
  );
89
330
  assertEquals(2, records.size());
90
- assertEquals("John", records.get(0)[0]);
91
- assertEquals("David", records.get(1)[0]);
331
+ assertEquals(Long.valueOf(100), records.get(0)[0]);
332
+ assertEquals("A0?B1>", records.get(0)[1]);
333
+ assertEquals(Long.valueOf(101), records.get(1)[0]);
334
+ assertEquals("ab?cd~", records.get(1)[1]);
92
335
  }
93
336
  }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: embulk-filter-base64
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yusuke NISHIOKA
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-01-01 00:00:00.000000000 Z
11
+ date: 2017-01-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
@@ -38,7 +38,7 @@ dependencies:
38
38
  - - '>='
39
39
  - !ruby/object:Gem::Version
40
40
  version: '10.0'
41
- description: An Embulk filter plugin to encode/decode string by Base64.
41
+ description: An Embulk filter plugin to encode/decode string by Base64, Base32 and Base16.
42
42
  email:
43
43
  - yusuke.nishioka.0713@gmail.com
44
44
  executables: []
@@ -53,7 +53,6 @@ files:
53
53
  - config/checkstyle/default.xml
54
54
  - example/example_decode.csv
55
55
  - example/example_decode.yml
56
- - example/example_decode_with_typecast.yml
57
56
  - example/example_encode.csv
58
57
  - example/example_encode.yml
59
58
  - example/get_string.py
@@ -62,11 +61,12 @@ files:
62
61
  - gradlew
63
62
  - gradlew.bat
64
63
  - lib/embulk/filter/base64.rb
64
+ - src/main/java/org/embulk/filter/base64/Base64Filter.java
65
65
  - src/main/java/org/embulk/filter/base64/Base64FilterPlugin.java
66
66
  - src/main/java/org/embulk/filter/base64/ColumnVisitorImpl.java
67
67
  - src/test/java/org/embulk/filter/base64/TestBase64FilterPlugin.java
68
68
  - src/test/java/org/embulk/filter/base64/TestColumnVisitorImpl.java
69
- - classpath/embulk-filter-base64-0.1.1.jar
69
+ - classpath/embulk-filter-base64-0.2.0.jar
70
70
  homepage: https://github.com/ysk24ok/embulk-filter-base64
71
71
  licenses:
72
72
  - MIT
@@ -1,32 +0,0 @@
1
- in:
2
- type: file
3
- path_prefix: example/example_decode.csv
4
- parser:
5
- type: csv
6
- columns:
7
- - {name: id, type: long}
8
- - {name: string to decode, type: string}
9
- - {name: long to decode, type: string}
10
- - {name: double to decode, type: string}
11
- - {name: boolean to decode, type: string}
12
- - {name: timestamp to decode, type: string}
13
- - {name: json to decode, type: string}
14
- filters:
15
- - type: base64
16
- columns:
17
- - {name: string to decode, decode: true}
18
- - {name: long to decode, decode: true}
19
- - {name: double to decode, decode: true}
20
- - {name: boolean to decode, decode: true}
21
- - {name: timestamp to decode, decode: true}
22
- - {name: json to decode, decode: true}
23
- - type: typecast
24
- columns:
25
- - {name: string to decode, type: string}
26
- - {name: long to decode, type: long}
27
- - {name: double to decode, type: double}
28
- - {name: boolean to decode, type: boolean}
29
- - {name: timestamp to decode, type: timestamp, format: "%Y-%m-%d %H:%M:%N", timezone: "UTC"}
30
- - {name: json to decode, type: json}
31
- out:
32
- type: stdout