如何自定义JSON输出以获得更精细的细节

时间:2012-10-04 14:48:30

标签: java json

这适用于所有JSON大脑。

假设我有一个界面:

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

然后假设我有一个Item对象:

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
  4. 中的Item对象

    我希望输出是这样的:

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

    提前致谢!


    我认为我应该分享到目前为止我能够提供的内容,并获得您的反馈。它几乎满足了我的要求,但我不确定它是否正确:

    我在这里被一位用户指向了genson,我发现它非常有趣。

    首先我创建了一个Serializer

    公共类ModelSerializer实现了Serializer {

    @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并通过了Serializer

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

    现在,当我传递ViewModel时,我得到的格式符合我的预期

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

3 个答案:

答案 0 :(得分:0)

我会稍微重构你的代码。首先,您需要POCO类作为数据载体,这将是您的Item类。然后你需要一个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);     
}

....
}

然后你可以使用这个Repository(不是一个好主意直接在Controller中使用Repository。你宁愿想要返回一个ViewModel,它是一个包含你的视图所需属性的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

- 修改

抱歉,错过了您正在使用Java的一点。如上所述:

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

您可以将现有的Item Class修改为:

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?

答案 1 :(得分:0)

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

如果所需的输出是{name:'',dateCreated:'',timeCreated:'',lastUpdated:'',lastUpdatedTime:''}没有“item:”:

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

new Genson().serialize(myItemModel);

如果你想要“item”键,你也可以在wiki中实现自定义的Serializer或Converter。

答案 2 :(得分:0)

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