Skip to content

Commit 5263bbe

Browse files
committed
[JAVA-280]: BSONTimestamp and some other fields are not properly serialized to JSON and cannot be parsed back
1 parent 3621593 commit 5263bbe

File tree

6 files changed

+80
-18
lines changed

6 files changed

+80
-18
lines changed

src/main/com/mongodb/Bytes.java

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
import java.nio.charset.*;
2323
import java.util.regex.Pattern;
2424
import java.util.*;
25+
import java.util.concurrent.atomic.AtomicInteger;
26+
import java.util.concurrent.atomic.AtomicLong;
2527
import java.util.logging.*;
2628

2729
import org.bson.*;
@@ -150,7 +152,7 @@ void reset(){
150152
/**
151153
* Gets the type byte for a given object.
152154
* @param o the object
153-
* @return the byte value associated with the type, or 0 if <code>o</code> was <code>null</code>
155+
* @return the byte value associated with the type, or -1 if no type is matched
154156
*/
155157
@SuppressWarnings("deprecation")
156158
public static byte getType( Object o ){
@@ -160,6 +162,17 @@ public static byte getType( Object o ){
160162
if ( o instanceof DBPointer )
161163
return REF;
162164

165+
if (o instanceof Integer
166+
|| o instanceof Short
167+
|| o instanceof Byte
168+
|| o instanceof AtomicInteger) {
169+
return NUMBER_INT;
170+
}
171+
172+
if (o instanceof Long || o instanceof AtomicLong) {
173+
return NUMBER_LONG;
174+
}
175+
163176
if ( o instanceof Number )
164177
return NUMBER;
165178

@@ -181,13 +194,22 @@ public static byte getType( Object o ){
181194
if ( o instanceof java.util.Date )
182195
return DATE;
183196

197+
if ( o instanceof BSONTimestamp )
198+
return TIMESTAMP;
199+
184200
if ( o instanceof java.util.regex.Pattern )
185201
return REGEX;
186202

187-
if ( o instanceof DBObject )
203+
if ( o instanceof DBObject || o instanceof DBRefBase )
188204
return OBJECT;
189205

190-
return 0;
206+
if ( o instanceof Code )
207+
return CODE;
208+
209+
if ( o instanceof CodeWScope )
210+
return CODE_W_SCOPE;
211+
212+
return -1;
191213
}
192214

193215
static final ObjectId COLLECTION_REF_ID = new ObjectId( -1 , -1 , -1 );

src/main/com/mongodb/util/JSON.java

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,11 @@ public static void serialize( Object o , StringBuilder buf ){
146146
}
147147

148148
if (o instanceof DBRefBase) {
149-
buf.append(o);
149+
DBRefBase ref = (DBRefBase)o;
150+
BasicDBObject temp = new BasicDBObject();
151+
temp.put( "$ref" , ref.getRef() );
152+
temp.put( "$id" , ref.getId() );
153+
serialize( temp, buf );
150154
return;
151155
}
152156

@@ -182,7 +186,10 @@ public static void serialize( Object o , StringBuilder buf ){
182186

183187
if ( o instanceof BSONTimestamp ){
184188
BSONTimestamp t = (BSONTimestamp)o;
185-
buf.append( t.getTime() ).append( "|" ).append( t.getInc() );
189+
BasicDBObject temp = new BasicDBObject();
190+
temp.put( "$ts" , t.getTime() );
191+
temp.put( "$inc" , t.getInc() );
192+
serialize( temp, buf );
186193
return;
187194
}
188195

@@ -197,7 +204,10 @@ public static void serialize( Object o , StringBuilder buf ){
197204
}
198205

199206
if ( o instanceof Code ){
200-
string( buf , ((Code)o).getCode() );
207+
Code c = (Code)o;
208+
BasicDBObject temp = new BasicDBObject();
209+
temp.put( "$code" , c.getCode() );
210+
serialize( temp, buf );
201211
return;
202212
}
203213

@@ -561,9 +571,7 @@ public Number parseNumber() {
561571

562572
if (isDouble)
563573
return Double.valueOf(s.substring(start, pos));
564-
if ( pos - start >= 10 )
565-
return Long.valueOf(s.substring(start, pos));
566-
return Integer.valueOf(s.substring(start, pos));
574+
return Long.valueOf(s.substring(start, pos));
567575
}
568576

569577
/**

src/main/com/mongodb/util/JSONCallback.java

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,47 +24,73 @@ public BSONObject create( boolean array , List<String> path ){
2424
}
2525

2626
public void objectStart(boolean array, String name){
27-
_lastName = name;
2827
_lastArray = array;
2928
super.objectStart( array , name );
3029
}
3130

3231
public Object objectDone(){
32+
String name = curName();
3333
Object o = super.objectDone();
3434
BSONObject b = (BSONObject)o;
3535

36+
// override the object if it's a special type
3637
if ( ! _lastArray ) {
3738
if ( b.containsField( "$oid" ) ) {
3839
o = new ObjectId((String)b.get("$oid"));
3940
if (!isStackEmpty()) {
40-
gotObjectId( _lastName, (ObjectId)o);
41+
gotObjectId( name, (ObjectId)o);
4142
} else {
4243
setRoot(o);
43-
}
44+
}
4445
} else if ( b.containsField( "$date" ) ) {
4546
SimpleDateFormat format =
4647
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
4748
format.setCalendar(new GregorianCalendar(new SimpleTimeZone(0, "GMT")));
4849
o = format.parse((String)b.get("$date"), new ParsePosition(0));
4950
if (!isStackEmpty()) {
50-
cur().put( _lastName, o );
51+
cur().put( name, o );
5152
} else {
5253
setRoot(o);
5354
}
5455
} else if ( b.containsField( "$regex" ) ) {
5556
o = Pattern.compile( (String)b.get( "$regex" ),
5657
BSON.regexFlags( (String)b.get( "$options" )) );
5758
if (!isStackEmpty()) {
58-
cur().put( _lastName, o );
59+
cur().put( name, o );
60+
} else {
61+
setRoot(o);
62+
}
63+
} else if ( b.containsField( "$ts" ) ) {
64+
Long ts = (Long) b.get("$ts");
65+
Long inc = (Long) b.get("$ts");
66+
o = new BSONTimestamp(ts.intValue(), inc.intValue());
67+
if (!isStackEmpty()) {
68+
cur().put( name, o );
69+
} else {
70+
setRoot(o);
71+
}
72+
} else if ( b.containsField( "$code" ) ) {
73+
if (b.containsField("$scope")) {
74+
o = new CodeWScope((String)b.get("$code"), (DBObject)b.get("$scope"));
75+
} else {
76+
o = new Code((String)b.get("$code"));
77+
}
78+
if (!isStackEmpty()) {
79+
cur().put( name, o );
80+
} else {
81+
setRoot(o);
82+
}
83+
} else if ( b.containsField( "$ref" ) ) {
84+
o = new DBRefBase(null, (String)b.get("$ref"), b.get("$id"));
85+
if (!isStackEmpty()) {
86+
cur().put( name, o );
5987
} else {
6088
setRoot(o);
6189
}
6290
}
6391
}
64-
6592
return o;
6693
}
6794

68-
private String _lastName;
6995
private boolean _lastArray = false;
7096
}

src/main/org/bson/BasicBSONCallback.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,12 @@ protected BSONObject cur(){
154154
return _stack.getLast();
155155
}
156156

157+
protected String curName(){
158+
if (_nameStack.isEmpty())
159+
return null;
160+
return _nameStack.getLast();
161+
}
162+
157163
public Object get(){
158164
return _root;
159165
}

src/test/com/mongodb/ByteTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ public void testEncodeDecode() {
287287
obj = 5;
288288
o = new BasicDBObject();
289289
o.put( "$where", obj );
290-
assertEquals( Bytes.getType( obj ), Bytes.NUMBER );
290+
assertEquals( Bytes.getType( obj ), Bytes.NUMBER_INT );
291291
go( o, 17 );
292292
}
293293

src/test/com/mongodb/util/JSONTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ public void testBasic(){
193193
assertEquals(threw, false);
194194
threw = false;
195195

196-
assertEquals( 4 , JSON.parse( "4" ) );
196+
assertEquals( 4L , JSON.parse( "4" ) );
197197
}
198198

199199
@org.testng.annotations.Test

0 commit comments

Comments
 (0)