Skip to content

Commit 9cb1f34

Browse files
committed
Fix #16
1 parent 595674a commit 9cb1f34

File tree

5 files changed

+50693
-7
lines changed

5 files changed

+50693
-7
lines changed

release-notes/VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Project: jackson-dataformat-smile
22
Version: 2.4.0 (xx-xxx-2014)
33

4-
No changes since 2.3.
4+
#16: Support handling of "Stringified" numbers
55

66
------------------------------------------------------------------------
77
=== History: ===

src/main/java/com/fasterxml/jackson/dataformat/smile/SmileGenerator.java

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1439,14 +1439,63 @@ public void writeNumber(BigDecimal dec) throws IOException, JsonGenerationExcept
14391439
}
14401440

14411441
@Override
1442-
public void writeNumber(String encodedValue) throws IOException,JsonGenerationException, UnsupportedOperationException
1442+
public void writeNumber(String encodedValue) throws IOException
14431443
{
1444-
/* 17-Apr-2010, tatu: Could try parsing etc; but for now let's not bother, it could
1445-
* just be some non-standard representation that caller wants to pass
1446-
*/
1447-
throw _notSupported();
1444+
if (encodedValue == null) {
1445+
writeNull();
1446+
return;
1447+
}
1448+
1449+
// 28-May-2014, tatu: Let's actually try to support this method; should be doable
1450+
final int len = encodedValue.length();
1451+
boolean neg = encodedValue.startsWith("-");
1452+
1453+
// Let's see if it's integral or not
1454+
int i = neg ? 1 : 0;
1455+
while (true) {
1456+
char c = encodedValue.charAt(i);
1457+
if (c > '9' || c < '0') {
1458+
break;
1459+
}
1460+
if (++i == len) {
1461+
_writeIntegralNumber(encodedValue, neg);
1462+
return;
1463+
}
1464+
}
1465+
_writeDecimalNumber(encodedValue);
1466+
}
1467+
1468+
protected void _writeIntegralNumber(String enc, boolean neg) throws IOException
1469+
{
1470+
int len = enc.length();
1471+
if (neg) {
1472+
--len;
1473+
}
1474+
// let's do approximate optimization
1475+
try {
1476+
if (len <= 9) {
1477+
writeNumber(Integer.parseInt(enc));
1478+
} else if (len <= 18) {
1479+
writeNumber(Long.parseLong(enc));
1480+
} else {
1481+
writeNumber(new BigInteger(enc));
1482+
}
1483+
} catch (NumberFormatException e) {
1484+
throw new JsonGenerationException("Invalid String representation for Number ('"+enc
1485+
+"'); can not write using Smile format");
1486+
}
14481487
}
14491488

1489+
protected void _writeDecimalNumber(String enc) throws IOException
1490+
{
1491+
try {
1492+
writeNumber(new BigDecimal(enc));
1493+
} catch (NumberFormatException e) {
1494+
throw new JsonGenerationException("Invalid String representation for Number ('"+enc
1495+
+"'); can not write using Smile format");
1496+
}
1497+
}
1498+
14501499
/*
14511500
/**********************************************************
14521501
/* Implementations for other methods
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
package com.fasterxml.jackson.dataformat.smile;
2+
3+
import java.util.*;
4+
5+
import com.fasterxml.jackson.databind.*;
6+
7+
/**
8+
* Bigger test to try to do smoke-testing of overall functionality,
9+
* using more sizable (500k of JSON, 200k of Smile) dataset.
10+
* Should tease out at least some of boundary conditions.
11+
*/
12+
public class TestBiggerData extends SmileTestBase
13+
{
14+
static class Citm
15+
{
16+
public Map<Integer,String> areaNames;
17+
public Map<Integer,String> audienceSubCategoryNames;
18+
public Map<Integer,String> blockNames;
19+
public Map<Integer,String> seatCategoryNames;
20+
public Map<Integer,String> subTopicNames;
21+
public Map<Integer,String> subjectNames;
22+
public Map<Integer,String> topicNames;
23+
public Map<Integer,int[]> topicSubTopics;
24+
public Map<String,String> venueNames;
25+
26+
public Map<Integer,Event> events;
27+
public List<Performance> performances;
28+
}
29+
30+
static class Event
31+
{
32+
public int id;
33+
public String name;
34+
public String description;
35+
public String subtitle;
36+
public String logo;
37+
public int subjectCode;
38+
public int[] topicIds;
39+
public LinkedHashSet<Integer> subTopicIds;
40+
}
41+
42+
static class Performance
43+
{
44+
public int id;
45+
public int eventId;
46+
public String name;
47+
public String description;
48+
public String logo;
49+
50+
public List<Price> prices;
51+
public List<SeatCategory> seatCategories;
52+
53+
public long start;
54+
public String seatMapImage;
55+
public String venueCode;
56+
}
57+
58+
static class Price {
59+
public int amount;
60+
public int audienceSubCategoryId;
61+
public int seatCategoryId;
62+
}
63+
64+
static class SeatCategory {
65+
public int seatCategoryId;
66+
public List<Area> areas;
67+
}
68+
69+
static class Area {
70+
public int areaId;
71+
public int[] blockIds;
72+
}
73+
74+
/*
75+
/**********************************************************
76+
/* Test methods
77+
/**********************************************************
78+
*/
79+
80+
final ObjectMapper JSON_MAPPER = new ObjectMapper();
81+
82+
public void testReading() throws Exception
83+
{
84+
Citm citm0 = JSON_MAPPER.readValue(getClass().getResourceAsStream("/data/citm_catalog.json"),
85+
Citm.class);
86+
87+
ObjectMapper smiler = smileMapper(false);
88+
byte[] smile = smiler.writeValueAsBytes(citm0);
89+
90+
Citm citm = smiler.readValue(smile, Citm.class);
91+
92+
assertNotNull(citm);
93+
assertNotNull(citm.areaNames);
94+
assertEquals(17, citm.areaNames.size());
95+
assertNotNull(citm.events);
96+
assertEquals(184, citm.events.size());
97+
98+
assertNotNull(citm.seatCategoryNames);
99+
assertEquals(64, citm.seatCategoryNames.size());
100+
assertNotNull(citm.subTopicNames);
101+
assertEquals(19, citm.subTopicNames.size());
102+
assertNotNull(citm.subjectNames);
103+
assertEquals(0, citm.subjectNames.size());
104+
assertNotNull(citm.topicNames);
105+
assertEquals(4, citm.topicNames.size());
106+
assertNotNull(citm.topicSubTopics);
107+
assertEquals(4, citm.topicSubTopics.size());
108+
assertNotNull(citm.venueNames);
109+
assertEquals(1, citm.venueNames.size());
110+
}
111+
112+
public void testRoundTrip() throws Exception
113+
{
114+
Citm citm0 = JSON_MAPPER.readValue(getClass().getResourceAsStream("/data/citm_catalog.json"),
115+
Citm.class);
116+
ObjectMapper smiler = smileMapper(false);
117+
byte[] smile = smiler.writeValueAsBytes(citm0);
118+
119+
Citm citm = smiler.readValue(smile, Citm.class);
120+
121+
ObjectMapper mapper = smileMapper(false);
122+
123+
byte[] smile1 = mapper.writeValueAsBytes(citm);
124+
Citm citm2 = mapper.readValue(smile1, Citm.class);
125+
byte[] smile2 = mapper.writeValueAsBytes(citm2);
126+
127+
assertEquals(smile1.length, smile2.length);
128+
129+
assertNotNull(citm.areaNames);
130+
assertEquals(17, citm.areaNames.size());
131+
assertNotNull(citm.events);
132+
assertEquals(184, citm.events.size());
133+
134+
assertEquals(citm.seatCategoryNames.size(), citm2.seatCategoryNames.size());
135+
assertEquals(citm.subTopicNames.size(), citm2.subTopicNames.size());
136+
assertEquals(citm.subjectNames.size(), citm2.subjectNames.size());
137+
assertEquals(citm.topicNames.size(), citm2.topicNames.size());
138+
assertEquals(citm.topicSubTopics.size(), citm2.topicSubTopics.size());
139+
assertEquals(citm.venueNames.size(), citm2.venueNames.size());
140+
}
141+
}

src/test/java/com/fasterxml/jackson/dataformat/smile/TestGeneratorNumbers.java

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,33 @@ public void testDoubles() throws Exception
126126
gen.writeNumber(0.125);
127127
gen.close();
128128
assertEquals(11, out.toByteArray().length);
129-
}
129+
}
130+
131+
// #16: Problems with 'Stringified' numbers
132+
public void testNumbersAsString() throws Exception
133+
{
134+
ByteArrayOutputStream out;
135+
SmileGenerator gen;
136+
137+
// first int
138+
out = new ByteArrayOutputStream();
139+
gen = smileGenerator(out, false);
140+
gen.writeNumber("15");
141+
gen.close();
142+
_verifyBytes(out.toByteArray(), (byte) (0xC0 + SmileUtil.zigzagEncode(15)));
130143

144+
// then long. Note: cut-off to BigInteger not exact, so...
145+
out = new ByteArrayOutputStream();
146+
gen = smileGenerator(out, false);
147+
gen.writeNumber(String.valueOf(-1L + Integer.MIN_VALUE));
148+
gen.close();
149+
assertEquals(6, out.toByteArray().length);
150+
151+
// and then just BigDecimal...
152+
out = new ByteArrayOutputStream();
153+
gen = smileGenerator(out, false);
154+
gen.writeNumber("-50.00000000125");
155+
gen.close();
156+
assertEquals(10, out.toByteArray().length);
157+
}
131158
}

0 commit comments

Comments
 (0)