Skip to content

Commit 9cf4426

Browse files
committed
Merge branch '2.9'
2 parents a66bee1 + 3bb1792 commit 9cf4426

File tree

15 files changed

+213
-140
lines changed

15 files changed

+213
-140
lines changed

release-notes/VERSION

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,14 @@ Modules:
1010

1111
2.9.3 (not yet released)
1212

13+
#39 (yamk): Binary data not recognized by YAML parser
14+
(repoted by tmoschou@github)
1315
#42 (csv): Add support for escaping double quotes with the configured escape character
1416
(contributed by frankgrimes97@github)
1517
#51 (csv): Set of custom objects with `IGNORE_UNKNOWN` brokes silently csv
1618
(reported by Simone L)
17-
#39 (yamk): Binary data not recognized by YAML parser
18-
(repoted by tmoschou@github)
19+
#53: (yaml) Binary values written without type tag
20+
(reported by arulrajnet@github)
1921

2022
2.9.2 (14-Oct-2017)
2123

yaml/src/main/java/com/fasterxml/jackson/dataformat/yaml/YAMLGenerator.java

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
import org.yaml.snakeyaml.DumperOptions.FlowStyle;
1313
import org.yaml.snakeyaml.emitter.Emitter;
1414
import org.yaml.snakeyaml.events.*;
15+
import org.yaml.snakeyaml.external.biz.base64Coder.Base64Coder;
16+
import org.yaml.snakeyaml.nodes.Tag;
1517

1618
import com.fasterxml.jackson.core.*;
1719
import com.fasterxml.jackson.core.base.GeneratorBase;
@@ -139,6 +141,7 @@ private Feature(boolean defaultState) {
139141
protected final static long MIN_INT_AS_LONG = (long) Integer.MIN_VALUE;
140142
protected final static long MAX_INT_AS_LONG = (long) Integer.MAX_VALUE;
141143
protected final static Pattern PLAIN_NUMBER_P = Pattern.compile("[0-9]*(\\.[0-9]*)?");
144+
protected final static String TAG_BINARY = Tag.BINARY.toString();
142145

143146
/*
144147
/**********************************************************
@@ -170,7 +173,8 @@ private Feature(boolean defaultState) {
170173
private final static Character STYLE_LITERAL = Character.valueOf('|');
171174

172175
// Which flow style to use for Base64? Maybe basic quoted?
173-
private final static Character STYLE_BASE64 = Character.valueOf('"');
176+
// 29-Nov-2017, tatu: Actually SnakeYAML uses block style so:
177+
private final static Character STYLE_BASE64 = STYLE_LITERAL;
174178

175179
private final static Character STYLE_PLAIN = null;
176180

@@ -593,12 +597,10 @@ public void writeBinary(Base64Variant b64variant, byte[] data, int offset, int l
593597
return;
594598
}
595599
_verifyValueWrite("write Binary value");
596-
// ok, better just Base64 encode as a String...
597600
if (offset > 0 || (offset+len) != data.length) {
598601
data = Arrays.copyOfRange(data, offset, offset+len);
599602
}
600-
String encoded = b64variant.encode(data);
601-
_writeScalar(encoded, "byte[]", STYLE_BASE64);
603+
_writeScalarBinary(data);
602604
}
603605

604606
/*
@@ -762,13 +764,24 @@ protected void _releaseBuffers() {
762764
*/
763765

764766
// Implicit means that (type) tags won't be shown, right?
765-
private final static ImplicitTuple DEFAULT_IMPLICIT = new ImplicitTuple(true, true);
767+
private final static ImplicitTuple NO_TAGS = new ImplicitTuple(true, true);
768+
769+
// ... and sometimes we specifically DO want explicit tag:
770+
private final static ImplicitTuple EXPLICIT_TAGS = new ImplicitTuple(false, false);
766771

767772
protected void _writeScalar(String value, String type, Character style) throws IOException
768773
{
769774
_emitter.emit(_scalarEvent(value, style));
770775
}
771776

777+
private void _writeScalarBinary(byte[] data) throws IOException
778+
{
779+
// 29-Nov-2017, tatu: Use SnakeYAML encoder instead of Jackson's
780+
String encoded = Base64Coder.encodeLines(data);
781+
_emitter.emit(new ScalarEvent(null, TAG_BINARY, EXPLICIT_TAGS, encoded,
782+
null, null, STYLE_BASE64));
783+
}
784+
772785
protected ScalarEvent _scalarEvent(String value, Character style)
773786
{
774787
String yamlTag = _typeId;
@@ -779,7 +792,9 @@ protected ScalarEvent _scalarEvent(String value, Character style)
779792
if (anchor != null) {
780793
_objectId = null;
781794
}
782-
return new ScalarEvent(anchor, yamlTag, DEFAULT_IMPLICIT, value,
795+
// 29-Nov-2017, tatu: Not 100% sure why we don't force explicit tags for
796+
// type id, but trying to do so seems to double up tag output...
797+
return new ScalarEvent(anchor, yamlTag, NO_TAGS, value,
783798
null, null, style);
784799
}
785800
}

yaml/src/test/java/com/fasterxml/jackson/dataformat/yaml/EventsTest.java

Lines changed: 0 additions & 52 deletions
This file was deleted.

yaml/src/test/java/com/fasterxml/jackson/dataformat/yaml/TypeIdTest.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ public void testNativeSerialization() throws Exception
3939
assertEquals("--- !<impl>\na: 13", yaml);
4040
}
4141

42-
// [Issue#22]
4342
public void testNonNativeSerialization() throws Exception
4443
{
4544
YAMLMapper mapper = new YAMLMapper();

yaml/src/test/java/com/fasterxml/jackson/dataformat/yaml/DatabindAdvancedTest.java renamed to yaml/src/test/java/com/fasterxml/jackson/dataformat/yaml/deser/DatabindAdvancedTest.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
package com.fasterxml.jackson.dataformat.yaml;
1+
package com.fasterxml.jackson.dataformat.yaml.deser;
22

33
import java.util.ArrayList;
44
import java.util.List;
55

66
import com.fasterxml.jackson.databind.ObjectMapper;
7+
import com.fasterxml.jackson.dataformat.yaml.ModuleTestBase;
78

89
public class DatabindAdvancedTest extends ModuleTestBase
910
{
@@ -135,7 +136,7 @@ public Image(String uri, String title, int w, int h, Size s)
135136
/**********************************************************
136137
*/
137138

138-
public void testBasic() throws Exception
139+
public void testReadComplexPojo() throws Exception
139140
{
140141
ObjectMapper mapper = newObjectMapper();
141142
String YAML =

yaml/src/test/java/com/fasterxml/jackson/dataformat/yaml/SimpleDatabindTest.java renamed to yaml/src/test/java/com/fasterxml/jackson/dataformat/yaml/deser/DatabindReadTest.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.fasterxml.jackson.dataformat.yaml;
1+
package com.fasterxml.jackson.dataformat.yaml.deser;
22

33
import java.io.ByteArrayInputStream;
44
import java.util.Map;
@@ -8,12 +8,13 @@
88

99
import com.fasterxml.jackson.databind.ObjectMapper;
1010
import com.fasterxml.jackson.databind.SerializationFeature;
11+
import com.fasterxml.jackson.dataformat.yaml.ModuleTestBase;
1112

1213
/**
1314
* Unit tests for checking functioning of the databinding
1415
* on top of YAML layer.
1516
*/
16-
public class SimpleDatabindTest extends ModuleTestBase
17+
public class DatabindReadTest extends ModuleTestBase
1718
{
1819
static class EmptyBean {
1920
}

yaml/src/test/java/com/fasterxml/jackson/dataformat/yaml/SimpleParseTest.java renamed to yaml/src/test/java/com/fasterxml/jackson/dataformat/yaml/deser/SimpleParseTest.java

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1-
package com.fasterxml.jackson.dataformat.yaml;
1+
package com.fasterxml.jackson.dataformat.yaml.deser;
22

33
import com.fasterxml.jackson.core.JsonParser;
44
import com.fasterxml.jackson.core.JsonToken;
5+
import com.fasterxml.jackson.dataformat.yaml.ModuleTestBase;
6+
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
7+
import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;
8+
import com.fasterxml.jackson.dataformat.yaml.YAMLParser;
59

610
import java.io.StringWriter;
711
import java.math.BigInteger;
@@ -14,6 +18,47 @@ public class SimpleParseTest extends ModuleTestBase
1418
{
1519
final YAMLMapper MAPPER = newObjectMapper();
1620

21+
public void testBasic() throws Exception
22+
{
23+
final String YAML =
24+
"string: 'text'\n"
25+
+"bool: true\n"
26+
+"bool2: false\n"
27+
+"null: null\n"
28+
+"i: 123\n"
29+
+"d: 1.25\n"
30+
;
31+
JsonParser p = MAPPER.createParser(YAML);
32+
assertToken(JsonToken.START_OBJECT, p.nextToken());
33+
34+
assertToken(JsonToken.FIELD_NAME, p.nextToken());
35+
assertToken(JsonToken.VALUE_STRING, p.nextToken());
36+
assertEquals("text", p.getText());
37+
assertToken(JsonToken.FIELD_NAME, p.nextToken());
38+
assertToken(JsonToken.VALUE_TRUE, p.nextToken());
39+
assertEquals("true", p.getText());
40+
assertToken(JsonToken.FIELD_NAME, p.nextToken());
41+
assertToken(JsonToken.VALUE_FALSE, p.nextToken());
42+
assertEquals("false", p.getText());
43+
assertToken(JsonToken.FIELD_NAME, p.nextToken());
44+
assertToken(JsonToken.VALUE_NULL, p.nextToken());
45+
assertEquals("null", p.getText());
46+
assertToken(JsonToken.FIELD_NAME, p.nextToken());
47+
assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken());
48+
assertEquals("123", p.getText());
49+
assertEquals(123, p.getIntValue());
50+
assertToken(JsonToken.FIELD_NAME, p.nextToken());
51+
assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken());
52+
assertEquals("1.25", p.getText());
53+
assertEquals(1.25, p.getDoubleValue());
54+
assertEquals(1, p.getIntValue());
55+
56+
assertToken(JsonToken.END_OBJECT, p.nextToken());
57+
assertNull(p.nextToken());
58+
assertNull(p.nextToken());
59+
assertNull(p.nextToken());
60+
p.close();
61+
}
1762
// Parsing large numbers around the transition from int->long and long->BigInteger
1863
public void testIntParsing() throws Exception
1964
{

yaml/src/test/java/com/fasterxml/jackson/dataformat/yaml/UTF8ReaderTest.java renamed to yaml/src/test/java/com/fasterxml/jackson/dataformat/yaml/deser/UTF8ReaderTest.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
package com.fasterxml.jackson.dataformat.yaml;
1+
package com.fasterxml.jackson.dataformat.yaml.deser;
22

33
import org.junit.Test;
44

5+
import com.fasterxml.jackson.dataformat.yaml.UTF8Reader;
6+
57
import java.io.ByteArrayInputStream;
68
import java.io.IOException;
79
import java.io.InputStream;
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package com.fasterxml.jackson.dataformat.yaml.ser;
2+
3+
import org.junit.Assert;
4+
5+
import com.fasterxml.jackson.databind.*;
6+
import com.fasterxml.jackson.databind.node.JsonNodeType;
7+
import com.fasterxml.jackson.databind.node.ObjectNode;
8+
import com.fasterxml.jackson.dataformat.yaml.ModuleTestBase;
9+
10+
public class BinaryWriteTest extends ModuleTestBase
11+
{
12+
private final ObjectMapper MAPPER = newObjectMapper();
13+
14+
public void testBinaryViaTree() throws Exception
15+
{
16+
byte[] srcPayload = new byte[] { 1, 2, 3, 4, 5 };
17+
ObjectNode root = MAPPER.createObjectNode();
18+
root.put("payload", srcPayload);
19+
String doc = MAPPER.writeValueAsString(root);
20+
21+
// and read back
22+
final JsonNode bean = MAPPER.readTree(doc);
23+
final JsonNode data = bean.get("payload");
24+
assertNotNull(data);
25+
assertEquals(JsonNodeType.BINARY, data.getNodeType());
26+
final byte[] b = data.binaryValue();
27+
Assert.assertArrayEquals(srcPayload, b);
28+
}
29+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package com.fasterxml.jackson.dataformat.yaml.ser;
2+
3+
import java.io.BufferedReader;
4+
import java.io.File;
5+
import java.io.FileInputStream;
6+
import java.io.InputStreamReader;
7+
import java.util.HashMap;
8+
import java.util.Iterator;
9+
import java.util.Map;
10+
import java.util.TreeSet;
11+
12+
import com.fasterxml.jackson.databind.ObjectMapper;
13+
import com.fasterxml.jackson.databind.node.ObjectNode;
14+
import com.fasterxml.jackson.dataformat.yaml.ModuleTestBase;
15+
16+
public class DatabindWriteTest extends ModuleTestBase
17+
{
18+
public void testBasicPOJO() throws Exception
19+
{
20+
ObjectMapper mapper = newObjectMapper();
21+
FiveMinuteUser user = new FiveMinuteUser("Bob", "Dabolito", false,
22+
FiveMinuteUser.Gender.MALE, new byte[] { 1, 3, 13, 79 });
23+
String yaml = mapper.writeValueAsString(user).trim();
24+
String[] parts = yaml.split("\n");
25+
// unify ordering, need to use TreeSets to get alphabetic ordering
26+
TreeSet<String> exp = new TreeSet<String>();
27+
for (String part : parts) {
28+
exp.add(part.trim());
29+
}
30+
Iterator<String> it = exp.iterator();
31+
assertEquals("---", it.next());
32+
assertEquals("AQMNTw==", it.next());
33+
assertEquals("firstName: \"Bob\"", it.next());
34+
assertEquals("gender: \"MALE\"", it.next());
35+
assertEquals("lastName: \"Dabolito\"", it.next());
36+
assertEquals("userImage: !!binary |", it.next());
37+
assertEquals("verified: false", it.next());
38+
assertFalse(it.hasNext());
39+
}
40+
41+
public void testWithFile() throws Exception
42+
{
43+
File f = File.createTempFile("test", ".yml");
44+
f.deleteOnExit();
45+
ObjectMapper mapper = newObjectMapper();
46+
Map<String,Integer> map = new HashMap<String,Integer>();
47+
map.put("a", 3);
48+
mapper.writeValue(f, map);
49+
assertTrue(f.canRead());
50+
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(
51+
f), "UTF-8"));
52+
String doc = br.readLine();
53+
String str = br.readLine();
54+
if (str != null) {
55+
doc += "\n" + str;
56+
}
57+
doc = trimDocMarker(doc);
58+
assertEquals("a: 3", doc);
59+
br.close();
60+
f.delete();
61+
}
62+
63+
public void testWithFile2() throws Exception
64+
{
65+
File f = File.createTempFile("test", ".yml");
66+
f.deleteOnExit();
67+
ObjectMapper mapper = newObjectMapper();
68+
ObjectNode root = mapper.createObjectNode();
69+
root.put("name", "Foobar");
70+
mapper.writeValue(f, root);
71+
72+
// and get it back
73+
Map<?,?> result = mapper.readValue(f, Map.class);
74+
assertEquals(1, result.size());
75+
assertEquals("Foobar", result.get("name"));
76+
}
77+
}

0 commit comments

Comments
 (0)