Json <-> Java serialization that works with GWT [closed] - json

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
I am looking for a simple Json (de)serializer for Java that might work with GWT. I have googled a bit and found some solutions that either require annotate every member or define useless interfaces. Quite a boring. Why don't we have something really simple like
class MyBean {
...
}
new GoodSerializer().makeString(new MyBean());
new GoodSerializer().makeObject("{ ... }", MyBean.class)

Take a look at GWT's Overlay Types. I think this is by far the easiest way to work with JSON in GWT. Here's a modified code example from the linked article:
public class Customer extends JavaScriptObject {
public final native String getFirstName() /*-{
return this.first_name;
}-*/;
public final native void setFirstName(String value) /*-{
this.first_name = value;
}-*/;
public final native String getLastName() /*-{
return this.last_name;
}-*/;
public final native void setLastName(String value) /*-{
this.last_name = value;
}-*/;
}
Once you have the overlay type defined, it's easy to create a JavaScript object from JSON and access its properties in Java:
public static final native Customer buildCustomer(String json) /*-{
return eval('(' + json + ')');
}-*/;
If you want the JSON representation of the object again, you can wrap the overlay type in a JSONObject:
Customer customer = buildCustomer("{'Bart', 'Simpson'}");
customer.setFirstName("Lisa");
// Displays {"first_name":"Lisa","last_name":"Simpson"}
Window.alert(new JSONObject(customer).toString());

Another thing to try is the new AutoBean framework introduced with GWT 2.1.
You define interfaces for your beans and a factory that vends them, and GWT generates implementations for you.
interface MyBean {
String getFoo();
void setFoo(String foo);
}
interface MyBiggerBean {
List<MyBean> getBeans();
void setBeans(List<MyBean> beans>;
}
interface Beanery extends AutoBeanFactory{
AutoBean<MyBean> makeBean();
AutoBean<MyBiggerBean> makeBigBean();
}
Beanery beanFactory = GWT.create(Beanery.class);
void go() {
MyBean bean = beanFactory.makeBean().as();
bean.setFoo("Hello, beans");
}
The AutoBeanCodex can be used to serialize them to and from json.
AutoBean<MyBean> autoBean = AutoBeanUtils.getAutoBean(bean);
String asJson = AutoBeanCodex.encode(autoBean).getPayload();
AutoBean<MyBean> autoBeanCloneAB =
AutoBeanCodex.decode(beanFactory, MyBean.class, asJson );
MyBean autoBeanClone = autoBeanCloneAB.as();
assertTrue(AutoBeanUtils.deepEquals(autoBean, autoBeanClone));
They work on the server side too — use AutoBeanFactoryMagic.create(Beanery.class) instead of GWT.create(Beanery.class).

The simplest way would be to use GWT's built-in JSON API. Here's the documentation. And here is a great tutorial on how to use it.
It's as simple as this:
String json = //json string
JSONValue value = JSONParser.parse(json);
The JSONValue API is pretty cool. It lets you chain validations as you extract values from the JSON object so that exceptions will be thrown if anything's amiss with the format.

It seems that I found the right answer to my question
I figured out that bean to json and json to bean conversion in GWT isn't a trivial task. Known libraries would not work because GWT would require their full source code and this source code must use only Java classes that are amoung emulated by GWT. Also, you cannot use reflection in GWT. Very tough requirements!
I found the only existing solution named gwt-jsonizer. It uses a custom Generator class and requires a satellite interface for each "jsonable" bean. Unfortunately, it does not work without patching on the latest version of GWT and has not been updated for a long time.
So, I personally decided that it is cheaper and faster to make my beans khow how to convert themselves to and from json. Like this:
public class SmartBean {
private String name;
public String getName() { return name; }
public void setName(String value) { name = value; }
public JSONObject toJson() {
JSONObject result = new JSONObject();
result.put("name", new JSONString(this.name));
return result;
}
public void fromJson(JSONObject value) {
this.name = value.get("name").isString().stringValue();
}
}
JSONxxxx are GWT built-in classes that provide low-level json support.

RestyGWT is a powerful library for encoding or decoding Java Object to JSON in GWT:
import javax.ws.rs.POST;
...
public interface PizzaOrderCodec extends JsonEncoderDecoder<PizzaOrder> {
}
Then:
// GWT will implement the interface for you
PizzaOrderCodec codec = GWT.create(PizzaOrderCodec.class);
// Encoding an object to json
PizzaOrder order = ...
JSONValue json = codec.encode(order);
// decoding an object to from json
PizzaOrder other = codec.decode(json);
It has also got several easy to use API for consuming Restful web services.
Have a nice time.

Check this:
GWT Professional JSON Serializer:
http://code.google.com/p/gwtprojsonserializer/
!Works with GWT 2.0+!

json.org/java seems to be included with GWT these days:
gwt-servlet-deps.jar\org\json\
Or, this project seems to be comprehensive:
http://code.google.com/p/piriti/

In Google Web Toolkit Applications, pages 510 to 522, the author, Ryan Dewsbury, shows how to use GWT code generation to do serialization to and from XML and JSON documents.
You can download the code here; you want the chapter 10 code bundles, and then you want to look in the src/com/gwtapps/serialization package. I did not see a license for this code, but have emailed the author to see what he says. I'll update this if he replies.
Issues with this solution:
You have to add a marker interface on all your objects that you want serialized (he uses java.io.Serializable but I imagine you could use others--if you are using hibernate for your backend, your pojos might already be tagged like this).
The code only supports string properties; it could be extended.
The code is only written for 1.4 and 1.5.
So, this is not an out of the box solution, but a great starting point for someone to build a JSON serializer that fits with GWT. Combine that with a JSON serializer on the server side, like json-lib and you're good to go.
I also found this project (again, some marker interface is required).

Try this serializer from Google Code: http://code.google.com/p/json-io/
If you need to write or read JSON format in Java, this is the tool to use. No need to create extra classes, etc. Convert a Java object graph to JSON format in one call. Do the opposite - create a JSON String or Stream to Java objects. This is the fastest library I have seen yet to do this. It is faster than ObjectOutputStream and ObjectInputStream in most cases, which use binary format.
Very handy utility.

You may want to checkout this project https://gerrit.googlesource.com/gwtjsonrpc/
It's a library created in order to support a code review system for Android, Gerrit, but it's a stand-alone module meant to be embedded into any GWT project, not just Gerrit.
A reasonable tutorial is probably the README in the top level of the directory. It's quite similar to standard GWT RPC but it uses JSON encoding. It also has built-in XSRF protection.

I seem to be answering this question a lot...
There's a page on code.google.com titled Using GWT for JSON Mashups. It's (unfortunately) way over my head, as I'm not that familiar with GWT, so it may not be helpful.

OK, I deleted my previous answer because it turned out to be exactly what you didn't want.
I don't know how well it works with GWT, but we use the json-lib library to serialize objects in a normal Java project where I work.
It can create a JSONObject directly from a JavaBean, then use the resulting JSONObject's toString() method to get the actual JSON string back.
Likewise, it can also turn JSON back into a JavaBean.

Not sure if Jackson would work for you.
I don't know if there's GWT-specific you are looking for; if not it should work.
But its serialization/deserialization works quite well, like:
// read json, create object
ObjectMapper mapper = new ObjectMapper();
MyBean bean = mapper.readValue(jsonAsString, MyBean.class);
// and write out
StringWriter sw = new StringWriter();
mapper.writeValue(sw, user);
String jsonOut = sw.toString();
You do need accessors (getX() to serialize, setX() to deserialize; can annotate methods with other names), but that's about it.

Related

Spring 4 and RabbitMQ json type

I'm really stuck with cast Rabbit response to POJO. How to do it properly? On sprin.io just no practical example.
So I'm trying to do it with this
#Bean
public DefaultClassMapper typeMapper() {
DefaultClassMapper typeMapper = new DefaultClassMapper();
Map<String, Class> idClassMapping = new HashMap<String, Class>();
idClassMapping.put("range", Loan.class);
typeMapper.setIdClassMapping(idClassMapping);
//typeMapper.setDefaultType(Loan.class);
return typeMapper;
}
#Bean
public MessageConverter messageConverter(DefaultClassMapper defaultClassMapper){
JsonMessageConverter jsonMessageConverter = new JsonMessageConverter();
jsonMessageConverter.setClassMapper(defaultClassMapper);
return jsonMessageConverter;
}
"range" actually fake value from example. Also this really doesn't work type problemn on .setIdClassMapping() . Also I can't use default mapper because serve send header without type hinting field. And I have no control on this remote server. Data format always JSON.
Caused by: org.springframework.amqp.support.converter.MessageConversionException: failed to convert Message content. Could not resolve __TypeId__ in header
Any suggestions working example for marshalling/demarshalling Java objects. I have completely different class for send back value from my code. I'm using java 8.
Just write your own ClassMapper - don't use the default one if your decision criteria to choose the class type is not compatible with its internals.
Or, you can subclass the DefaultClassMapper and override getClassIdFieldName() to tell it which message property to use.

SpringBatch - how to set up via java config the JsonLineMapper for reading a simple json file

How to change from "setLineTokenizer(new DelimitedLineTokenizer()...)" to "JsonLineMapper" in the first code below? Basicaly, it is working with csv but I want to change it to read a simple json file. I found some threads here asking about complex json but this is not my case. Firstly I thought that I should use a very diferent approach from csv way, but after I read SBiAch05sample.pdf (see the link and snippet at the bottom), I understood that FlatFileItemReader can be used to read json format.
In almost similiar question, I can guess that I am not in the wrong direction. Please, I am trying to find the simplest but elegant and recommended way for fixing this snippet code. So, the wrapper below, unless I am really obligated to work this way, seems to go further. Additionally, the wrapper seems to me more Java 6 style than my tentative which takes advantage of anonimous method from Java 7 (as far as I can judge from studies). Please, any advise is higly appreciated.
//My Code
#Bean
#StepScope
public FlatFileItemReader<Message> reader() {
log.info("ItemReader >>");
FlatFileItemReader<Message> reader = new FlatFileItemReader<Message>();
reader.setResource(new ClassPathResource("test_json.js"));
reader.setLineMapper(new DefaultLineMapper<Message>() {
{
setLineTokenizer(new DelimitedLineTokenizer() {
{
setNames(new String[] { "field1", "field2"...
//Sample using a wrapper
http://www.manning.com/templier/SBiAch05sample.pdf
import org.springframework.batch.item.file.LineMapper;
import org.springframework.batch.item.file.mapping.JsonLineMapper;
import com.manning.sbia.ch05.Product;
public class WrappedJsonLineMapper implements LineMapper<Product> {
private JsonLineMapper delegate;
public Product mapLine(String line, int lineNumber) throws Exception {
Map<String,Object> productAsMap
= delegate.mapLine(line, lineNumber);
Product product = new Product();
product.setId((String)productAsMap.get("id"));
product.setName((String)productAsMap.get("name"));
product.setDescription((String)productAsMap.get("description"));
product.setPrice(new Float((Double)productAsMap.get("price")));
return product;
}
public void setDelegate(JsonLineMapper delegate) {
this.delegate = delegate;
}
}
Really you have two options for parsing JSON within a Spring Batch job:
Don't create a LineMapper, create a LineTokenizer. Spring Batch's DefaultLineMapper breaks up the parsing of a record into two phases, parsing the record and mapping the result to an object. The fact that the incoming data is JSON vs a CSV only impacts the parsing piece (which is handled by the LineTokenizer). That being said, you'd have to write your own LineTokenizer to parse the JSON into a FieldSet.
Use the provided JsonLineMapper. Spring Batch provides a LineMapper implementation that uses Jackson to deserialize JSON objects into java objects.
In either case, you can't map a LineMapper to a LineTokenizer as they accomplish two different things.

Jersey/Genson: Unmarschalling single object array

Similar to Jersey: Json array with 1 element is serialized as object BUT on the client side. E.g. I recieve a JSON object where a field is an array regulary, but in case there is only one element, it is a single object.
{"fileInfo":[{"fileName":"weather.arff","id":"10"},"fileName":"supermarket.arff","id":"11"}]}
versus
{"fileInfo":{"fileName":"weather.arff","id":"10"}}
I'm parsing/unmarshalling the JSON using Jersey/Genson. Of course, if the JSON doesnt match the target class I recieve an error (such as expected [ but read '{' )
I've read a lot about this bug and how to avoid when creating JSON objects on the SERVER side, but I found nothing about how to handle this issus when dealing on the CLIENT side.
As always, I prefere the most codeless possibility if there are several solutions...
BTW: Moxy works but it does not marshal native Object-type objects which is another requirement...
Update
Starting with Genson 1.3 release you can achieve it by enabling permissiveParsing:
Genson genson = new GensonBuilder().usePermissiveParsing(true).create();
Answer
Uh, do you know what library produces this on server side? I am curious to see who is responsible for all those badly structured jsons out there...
It is not yet supported in Genson. Originally because IMO people should not produce such dynamic json. Anyway, I opened an issue - this can be easily done, you can expect it to be present in the release coming next week.
Otherwise here is a way to achieve it without breaking the existing mechanisms.
You need to register a Factory that will use Gensons collections factory to create an instance of its standard collection converter. Then you will wrap this converter in another one that will handle the object to array logic. Here is the code (not codeless..., but if you wait a bit you won't have to code :)).
import com.owlike.genson.convert.DefaultConverters.CollectionConverterFactory;
import com.owlike.genson.convert.DefaultConverters.CollectionConverterFactory;
class SingleObjectAsCollectionFactory implements Factory<Converter<Collection>> {
// get the default factory
Factory<Converter<Collection<?>>> defaultFactory = CollectionConverterFactory.instance;
#Override
public Converter<Collection> create(Type type, Genson genson) {
// obtain an instance of the correct default converter for this type
final CollectionConverter defaultConverter = (CollectionConverter) defaultFactory.create(type, genson);
// wrap it in your own converter
return new Converter<Collection>() {
#Override
public void serialize(Collection object, ObjectWriter writer, Context ctx) throws Exception {
defaultConverter.serialize(object, writer, ctx);
}
#Override
public Collection deserialize(ObjectReader reader, Context ctx) throws Exception {
if (reader.getValueType() == ValueType.OBJECT) {
Object object = defaultConverter.getElementConverter().deserialize(reader, ctx);
Collection result = defaultConverter.create();
result.add(object);
return result;
} else return defaultConverter.deserialize( reader, ctx );
}
};
}
}
And then register it
Genson genson = new GensonBuilder()
.withConverterFactory(new SingleObjectAsCollectionFactory())
.create();

Add JSON serializer to every model class?

When it comes to JSON encoding in Dart, per Seth Ladd's accouncement the finally approved now official way to go is dart:convert + JSON.Encode.
Let's say we have a bunch of model classes (PODOs) such as:
class Customer
{
int Id;
String Name;
}
Now, I'd love to be able to just JSON-encode my domain objects like this:
var customer = new Customer()
..Id = 17
..Name = "John";
var json = JSON.encode(customer);
Unfortunately, this won't work...
Uncaught Error: Converting object to an encodable object failed.
Stack Trace:
#0 _JsonStringifier.stringifyValue (dart:convert/json.dart:416)
#1 _JsonStringifier.stringify (dart:convert/json.dart:336)
#2 JsonEncoder.convert (dart:convert/json.dart:177)
....
... unless we explicitly tell dart:convert how to encode:
class Customer
{
int Id;
String Name;
Map toJson() {
Map map = new Map();
map["Id"] = Id;
map["Name"] = Name;
return map;
}
}
Do I really have to add a toJson method to every single one of my model classes, or is there a better way?
EDIT: this is the simple serialization I'm looking for:
{
"Id": 17,
"Name": "John"
}
Compare to ToJson in ServiceStack.Text, for instance.
Dart's serialization library (see Matt B's answer below) seems like a step in the right direction. However, this ...
var serialization = new Serialization()
..addRuleFor(Customer);
var json = JSON.encode(serialization.write(customer, format: new SimpleJsonFormat()));
... produces just an array with the values (no keys):
[17,"John"]
Using the default SimpleMapFormat on the other hand generates this complex representation.
Still haven't found what I'm looking for...
EDIT 2: Adding some context: I'm building a RESTful web service in Dart, and I'm looking for a JSON serialization which can easily be consumed by any client, not just another Dart client. For instance, querying the Stack Exchange API for this very question will create this JSON response. This is the serialization format I'm looking for. - Or, look at typical JSON responses returned by the Twitter REST API or the Facebook Graph API.
EDIT 3: I wrote a small blog post about this. See also the discussion on Hacker News.
IMO this is a major short-coming in Dart, surprising given its Web Application focus. I would've thought that having JSON support in the standard libraries would've meant that serializing classes to and from JSON would work like water, unfortunately the JSON support seems incomplete, where it appears the choices are to work with loosely typed maps or suffer through un-necessary boilerplate to configure your standard (PODO) classes to serialize as expected.
Without Reflection and Mirrors support
As popular Dart platforms like Flutter doesn't support Reflection/Mirrors your only option is to use a code-gen solution. The approach we've taken in ServiceStack's native support for Dart and Flutter lets you generate typed Dart models for all your ServiceStack Services from a remote URL, e.g:
$ npm install -g #servicestack/cli
$ dart-ref https://techstacks.io
Supported in .NET Core and any of .NET's popular hosting options.
The example above generates a Typed API for the .NET TechStacks project using the generated DTOs from techstacks.io/types/dart endpoint. This generates models following Dart's JsonCodec pattern where you can customize serialization for your Dart models by providing a fromJson named constructor and a toJson() instance method, here's an example of one of the generated DTOs:
class UserInfo implements IConvertible
{
String userName;
String avatarUrl;
int stacksCount;
UserInfo({this.userName,this.avatarUrl,this.stacksCount});
UserInfo.fromJson(Map<String, dynamic> json) { fromMap(json); }
fromMap(Map<String, dynamic> json) {
userName = json['userName'];
avatarUrl = json['avatarUrl'];
stacksCount = json['stacksCount'];
return this;
}
Map<String, dynamic> toJson() => {
'userName': userName,
'avatarUrl': avatarUrl,
'stacksCount': stacksCount
};
TypeContext context = _ctx;
}
With this model you can use Dart's built-in json:convert APIs to serialize and deserialize your model to JSON, e.g:
//Serialization
var dto = new UserInfo(userName:"foo",avatarUrl:profileUrl,stacksCount:10);
String jsonString = json.encode(dto);
//Deserialization
Map<String,dynamic> jsonObj = json.decode(jsonString);
var fromJson = new UserInfo.fromJson(jsonObj);
The benefit of this approach is that it works in all Dart platforms, including Flutter and AngularDart or Dart Web Apps with and without Dart 2’s Strong Mode.
The generated DTOs can also be used with servicestack's Dart package to enable an end to end typed solution which takes care JSON serialization into and out of your typed DTOs, e.g:
var client = new JsonServiceClient("https://www.techstacks.io");
var response = await client.get(new GetUserInfo(userName:"mythz"));
For more info see docs for ServiceStack's native Dart support.
Dart with Mirrors
If you're using Dart in a platform where Mirrors support is available I've found using a Mixin requires the least effort, e.g:
import 'dart:convert';
import 'dart:mirrors';
abstract class Serializable {
Map toJson() {
Map map = new Map();
InstanceMirror im = reflect(this);
ClassMirror cm = im.type;
var decls = cm.declarations.values.where((dm) => dm is VariableMirror);
decls.forEach((dm) {
var key = MirrorSystem.getName(dm.simpleName);
var val = im.getField(dm.simpleName).reflectee;
map[key] = val;
});
return map;
}
}
Which you can mixin with your PODO classes with:
class Customer extends Object with Serializable
{
int Id;
String Name;
}
Which you can now use with JSON.encode:
var c = new Customer()..Id = 1..Name = "Foo";
print(JSON.encode(c));
Result:
{"Id":1,"Name":"Foo"}
Note: see caveats with using Mirrors
I wrote the Exportable library to solve such things like converting to Map or JSON. Using it, the model declaration looks like:
import 'package:exportable/exportable.dart';
class Customer extends Object with Exportable {
#export int id;
#export String name;
}
And if you want to convert to JSON, you may:
String jsonString = customer.toJson();
Also, it's easy to initialize new object from a JSON string:
Customer customer = new Customer()..initFromJson(jsonString);
Or alternatively:
Customer customer = new Exportable(Customer, jsonString);
Please, see the README for more information.
An alternative is to use the Serialization package and add rules for your classes. The most basic form uses reflection to get the properties automatically.
Redstone mapper is the best serialization library I've used. JsonObject and Exportable have the downside that you have to extend some of their classes. With Redstone Mapper you can have structures like this
class News
{
#Field() String title;
#Field() String text;
#Field() List<FileDb> images;
#Field() String link;
}
It works with getters and setters, you can hide information by not annotating it with #Field(), you can rename field from/to json, have nested objects, it works on the server and client. It also integrates with the Redstone Server framework, where it has helpers to encode/decode to MongoDB.
The only other framework I've seen thats on the right direction is Dartson, but it still lack some features compared to Redstone Mapper.
I have solved with:
class Customer extends JsonObject
{
int Id;
String Name;
Address Addr;
}
class Address extends JsonObject{
String city;
String State;
String Street;
}
But my goal is bind data from/to json from/to model classes; This solution work if you can modify model classes, in a contrast you must use solution "external" to convert model classes;
see also: Parsing JSON list with JsonObject library in Dart
Another package solving this problem is built_value:
https://github.com/google/built_value.dart
With built_value your model classes look like this:
abstract class Account implements Built<Account, AccountBuilder> {
static Serializer<Account> get serializer => _$accountSerializer;
int get id;
String get name;
BuiltMap<String, JsonObject> get keyValues;
factory Account([updates(AccountBuilder b)]) = _$Account;
Account._();
}
Note that built_value isn't just about serialization -- it also provides operator==, hashCode, toString, and a builder class.
I have achieve with this:
To make this work, pass explicitToJson: true in the #JsonSerializable() annotation over the class declaration. The User class now looks as follows:
import 'address.dart';
import 'package:json_annotation/json_annotation.dart';
part 'user.g.dart';
#JsonSerializable(explicitToJson: true)
class User {
String firstName;
Address address;
User(this.firstName, this.address);
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
Map<String, dynamic> toJson() => _$UserToJson(this);
}
You can check here: https://flutter.dev/docs/development/data-and-backend/json#generating-code-for-nested-classes
I prefer using https://ashamp.github.io/jsonToDartModel/ online tool write by myself.
It has features below:
online use, without plugin
support multidimensional list
support complex json
support convert all props to String type
empty props warning
single file
dart keyword protected
instant convert
I think it's better than other tools.Welcome if you have any suggestion, issue or bug report.
Some of the answers are no longer applicable to Flutter 2; here is the process for automatically creating toJson and fromJson methods:
https://flutter.dev/docs/development/data-and-backend/json#creating-model-classes-the-json_serializable-way
PS: I wish this would be as simple as using Newtonsoft library in Asp.Net, this solution is closest to an automated solution

Can't make gwt json serialization work with overlay system - array always empty

I'm trying, for the first time, to parse json in gwt and it's not working. Since I'm a newbie this might be some obvious stupid mistake. The array is not retrieved correctly.
This is the piece of code on which I'm debugging:
String json = "{\"lokacije\":[{\"sifraLokacije\":1,\"nazivLokacije\":\"Policijska stanica\",\"brojDokumenata\":70}],\"status\":1}";
LocationsResponse locationsResponse = createLocationsResponse("("+json+")");
// this is ok, status is 1
int status = locationsResponse.getStatus();
// length of this array is 0 and you can see from json that it has one element (the same if it has more)
int brojLokacija = locationsResponse.getLokacije().length();
...
private final native LocationsResponse createLocationsResponse(String json) /*-{
return eval(json);
}-*/;
LocationsResponse class:
public class LocationsResponse extends JavaScriptObject {
protected LocationsResponse() {}
public final native int getStatus() /*-{ return this.status; }-*/;
public final native JsArray<JSOLokacija> getLokacije() /*-{ this.lokacije; }-*/;
}
JSOLokacija class:
public class JSOLokacija extends JavaScriptObject {
protected JSOLokacija() {} ;
public final native int getSifraLokacije() /*-{ this.sifraLokacije; }-*/;
public final native String getNazivLokacije() /*-{ this.nazivLokacije; }-*/;
public final native int getBrojDokumenata() /*-{ this.brojDokumenata; }-*/;
}
Second edit: Wow, I'm just useless today. My first answer returned JSONValue, which is pretty annoying if you want to work with a JSO.
Edit: Aaand just noticed your comment that you fixed it... Still, using the provided tools will tend to help prevent you from getting into annoying situations like this.
Here is another tool you should be aware of, esp if you are after using JSON, and not just objects from JS: AutoBeans (http://code.google.com/p/google-web-toolkit/wiki/AutoBean) - with these, you don't need to write out the JSNI code, just define the properties you expect to have, and it will work out all the wrapper code.
First, mostly useless answer:
eval doesn't work like that - it is meant to run JS, not turn JSON into data, and a json expression (also a js expression) isn't a legal statement in Javascript. Adding the "(" and ")" around the content is why it is working at all, but this is somewhat risky - usually it is better to trust the browser to do it right if possible:
Use JSONParser.parseStrict (or parseLenient if you expect parsing errors, but are absolutely certain that no possible attacks could be coming from there - this will end up calling eval for you, but this way you dont have to maintain it) instead to make sure the content is safe, and to parse it to js correctly. To turn this into a JSO then, you call .isObject().getJavaScriptObject() on the result of the parse method, which you then have to .cast() to the right value.