2012-10-04 15 views
0

这适用于所有JSON大脑。如何自定义JSON输出以获得更精细的细节

比方说,我有这样的接口:

public interface Model { 
    String getName(); 
    String getDateCreated(); 
    String getTimeCreated(); 
    String getLastUpdated(); 
    String getLastUpdatedTime(); 
} 

然后让我们说我有一个产品对象:

public class Item { 

    private String name; 
    private Date created; 
    private Date updated; 

    ..setters and getters 
} 

然后让我们说我有一个模型包装:

public class ItemModel implements Model { 

    private final Item item; 

    public ItemModel(Item item){ 
     this.item = item; 
    } 

    public String getName(){ 
     return item.getName(); 
    } 

    public String getDateCreated(){ 
     Date created = item.getCreated(); 
     //format the date nicely and return a date string 
    } 

    public String getTimeCreated(){ 
     Date created = item.getCreated(); 
     //format the date nicely and return a time string 
    } 

    ...you get the gyst, right? 
} 

问题是:

  1. 如何序列化ItemModel,以便json输出将反映模型接口上的getter名称?
  2. 具体来说,哪个库最容易做到这一点?你如何使用特定的库来实现这一目标?
  3. 最后,我不想要序列包裹ItemModel

内的项目对象我想要的输出是这样的:

{item : {name: '', dateCreated : '', timeCreated : '', lastUpdated : '', lastUpdatedTime : ''} 

提前感谢!


我以为我应该分享一下我迄今为止所能得到的,并得到您的反馈。这几乎满足我的要求,但我不确定它是否是正确的方式:

我被这里的用户指向了genson,我觉得它很有趣。

首先,我创建了一个串行

公共类ModelSerializer实现串行{

@Override 
public void serialize(T target, ObjectWriter writer, Context cntxt) throws TransformationException, IOException { 
    writer.beginObject(); 
    for (Method method : target.getClass().getMethods()) { 
     String methodName = method.getName(); 
     if (methodName.startsWith("get")) { 
      int index = "get".length(); 
      String valueName = Character.toLowerCase(methodName.charAt(index)) + method.getName().substring(index + 1); 
      try { 
       String valueString = (String) method.invoke(target, new Object[]{}); 
       writer.writeName(valueName).writeValue(valueString); 
      } catch (IllegalArgumentException ex) { 
       Logger.getLogger(ModelSerializer.class.getName()).log(Level.SEVERE, null, ex); 
       throw new TransformationException(ex.getMessage()); 
      } catch (IllegalAccessException ex) { 
       Logger.getLogger(ModelSerializer.class.getName()).log(Level.SEVERE, null, ex); 
       throw new TransformationException(ex.getMessage()); 
      } catch (InvocationTargetException ex) { 
       Logger.getLogger(ModelSerializer.class.getName()).log(Level.SEVERE, null, ex); 
       throw new TransformationException(ex.getMessage()); 
      } 
     } 
    } 
    writer.endObject(); 
} 

}

接下来,我创建Genson并通过串行

Genson genson =新Genson。 Builder()。withSerializer(new ModelSerializer(),Model.class).create();

现在,当我通过视图模型,我得到的领域格式如我所料

模型视图模型=新ItemModel(的DomainModel);其中domainModel是项目的一个实例 System.out.println(genson.serialize(viewModel));

+0

非常喜欢Genson!但你为什么要做所有的反思?你期望的确切输出是什么?您应该将您的序列化器定义为ModelSerializer实现序列化器 {... class code ...},然后使用Builder()。withConverters(new ModelSerializer())create()注册它。 – eugen

+0

为什么你不做新的Genson()。serialize(viewModel); ?你会得到与你的自定义序列化程序相同的输出(我测试了两种解决方案)。 – eugen

+0

您是否注意到Model接口仅返回字符串值,而Item返回字符串和日期?您必须为日期输出做一些格式设置,并且这导致了问题。 – mainas

回答

0

我会重构你的代码。首先你需要一个POCO类作为你的数据载体,这将是你的物品类。然后你会想要一个Repository为你做CRUD操作。

public interface IItemModelRepository { 
Item getItemByName(); 
Item getItemByDateCreated(); 
} 

你会实现的接口:

public class ItemModelRepository : IItemModelRepository { 

private IEnumerable<Item> _items; 

public ItemModelRepository() 
{ 
    this._items = /// Logic to load all items from database or from in memory cache 
} 

public Item getItemByName(string name){ 
    return this._items.First(i => i.Name.Equals(name); 
} 

public Item getItemByDateCreated(DateTime dateCreated){ 
    return this._items.First(i => i.DateCreated == dateCreated);  
} 

.... 
} 

然后你就可以使用这个仓库(不是一个好主意,直​​接在控制器使用存储库您宁愿要返回一个视图模型,这是包含由您的视图所需要的属性)一个POCO类:

var item = ItemModelRespository.GetByName("enter name here"); 
var viewModel = new ViewModel(); 
var serializer = new JavaScriptSerializer(); 
viewModel.JsonData = serializer.Serialize(item); 

而在客户端,你可以使用:

<%= Model.JsonData %> 

看看这里还有:ASP.NET MVC: How to convert View Model into Json object

--edit

对不起,错过了你使用的是Java位。这里提到:

http://flax.ie/flax-engine-gwt-client-side-json-serialization-and-deserialization/

你可以只修改现有的物品类别为:

public class Item implements JsonSerializable { 

    private String name; 
    private Date created; 
    private Date updated; 

..setters and getters 

/** 
* Pass this method JSON and it gives you back an object which you can 
* then assign to your object via MyObject x = JsonToObject(String Json); 
* 
* @param JSON 
* @return 
*/ 
public static Item JsonToObject(String Json) { 
    Serializer serializer = (Serializer) GWT.create(Serializer.class); 
    return (Item)serializer.deSerialize(Json,"your fully qualified Item assembly name"); 
} 

/** 
* Creates a JSON string from the current object 
* 
* @return String of JSON 
*/ 
public String toJson() { 
    Serializer serializer = (Serializer) GWT.create(Serializer.class); 
    return serializer.serialize(this); 
} 
} 

然后在你的代码消耗IItemModelRepository,你可以使用:

var item = ItemModelRepository.GetItemByName("name"); 
var jsonString = item.ToJson(); 

我没有得到的是,当你希望JSON输出是Item对象的序列化表示时,为什么要序列化ItemModel?

+0

感谢你的回应。您的解决方案是特定于.NET的。我正在寻找特定于java的解决方案。最接近我看到我的问题的一个可能的解决方案是与FlexJson变压器,但我仍然没有得到'变形金刚'概念的悬念。 – mainas

+0

检查我的更新回答..我不清楚您的要求 – tranceporter

+0

再次感谢。为了首先解决您的问题,我创作了一个名为commentit的库(http://code.google.com/p/commentit/),我正在对它进行调整。我遇到了一种情况,我希望ViewModel对象的通用接口将它们从域(数据库)对象中分离出来,这样它们就可以随着客户端的需求发展。我在服务器端使用模板框架来将html与模型对象合并 - 这很容易在这里调用接口方法。我也为客户端使用JSON。我想为JSON和模板框架维护相同的接口 – mainas

0

您可以尝试genson库它提供了几种方法来解决您的问题http://code.google.com/p/genson/

如果所需的输出为{名称: '',dateCreated会: '',timeCreated: '',LASTUPDATED: '',lastUpdatedTime: ''}无 “产品:”:

public class ItemModel implements Model {  
    @JsonIgnore private final Item item; 
    .... 
} 

new Genson().serialize(myItemModel); 

如果您想要“项目”键,您也可以实现像wiki这样的自定义串行器或转换器。

+0

genson看起来不错! – mainas

0

您可以使用像Jettison这样的库手动定义您自己的JSON映射,因此您不必用POJOS和POCO以及包装和其他愚蠢的东西扭曲自己。它确实不需要很多时间来设置映射。