如何为bean创建数据成员,用于使用Jackson解析器(或类似)解析JSON数据

时间:2011-07-15 13:32:01

标签: json javabeans jackson

我读了一些教程,说明应该使用getter和setter方法定义一个简单的bean,以系统的方式表示JSON数据。

下面给出的是我将要解析的数据,通过为这种情况定义bean来帮助我(其中一个节点包含许多节点,每个节点包含不同的子节点)

我要求from_title,from_url,to_title和to_url从JSON输出中获得大约2500条记录。

---------------- JSON DATA SAMPLE ----------------------------

{
"NOTICE" : [...terms of use appear here...]
"links" : [
{
"anchor_has_img" : false,
"anchor_text" : "",
"exclude" : false,
"follow" : true,
"from_host_rank10" : 3.48817529303454,
"from_ip" : "66.96.130.51",
"from_ip_geo" : {
"city" : "Burlington",
"country_code" : "US",
"isp_org" : "The Endurance International Group",
"latitude" : "42.5051",
"longitude" : "-71.2047",
"state" : "MA",
"zip" : "01803"
},
"from_pubdate" : 1287298800,
"from_rank10" : 4.1e-05,
"from_title" : "Antique Links",
"from_url" : "http://www.100tonsofstuff.com/links-antiquesresources.
htm",
"to_http_status" : 301,
"to_rank10" : 8.97651069961698,
"to_redir" : "http://geocities.yahoo.com/",
"to_title" : "Get a web site with easy-to-use site building tools -
Marengo Inn - Los Angeles Hotel - Yahoo - GeoCities",
"to_url" : "http://www.geocities.com/"
},
[...2499 entries skipped for this example...]
"nlinks_avail" : 2500,
"nlinks_est_total" : 11630.5708745538,
"to_rank10" : 8.97651069961698
}

2 个答案:

答案 0 :(得分:2)

这就是我要做的事。

import java.io.File;
import java.io.FileInputStream;
import java.math.BigDecimal;
import java.net.URI;
import java.util.Date;
import java.util.List;

import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.annotate.JsonAutoDetect.Visibility;
import org.codehaus.jackson.annotate.JsonProperty;
import org.codehaus.jackson.map.MapperConfig;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.PropertyNamingStrategy;
import org.codehaus.jackson.map.introspect.AnnotatedField;
import org.codehaus.jackson.map.introspect.AnnotatedMethod;

public class Foo
{
  public static void main(String[] args) throws Exception
  {
    ObjectMapper mapper = new ObjectMapper();
    mapper.setPropertyNamingStrategy(new CamelCaseToLowerCaseWithUnderscoresNamingStrategy());
    mapper.setVisibilityChecker(mapper.getVisibilityChecker().withFieldVisibility(Visibility.ANY));

    Response response = mapper.readValue(new File("input.json"), Response.class);
    String json = mapper.writeValueAsString(response);
    System.out.println(json);

    // Check for correctness
    JsonNode originalInput = mapper.readTree(new FileInputStream("input.json")); // next release of Jackson will have readTree that just takes a File object reference
    JsonNode generatedOutput = mapper.readTree(json);
    System.out.println("Are they the same?");
    System.out.println(originalInput.equals(generatedOutput) ? "yes" : "no");
  }
}

class Response
{
  @JsonProperty("NOTICE")
  String notice;
  List<Link> links;
  int nlinksAvail;
  BigDecimal nlinksEstTotal;
  BigDecimal toRank10;
}

class Link
{
  boolean anchorHasImg;
  String anchorText;
  boolean exclude;
  boolean follow;
  BigDecimal fromHostRank10;
  String fromIp;
  Geo fromIpGeo;
  Date fromPubdate;
  BigDecimal fromRank10;
  String fromTitle;
  URI fromUrl;
  int toHttpStatus;
  BigDecimal toRank10;
  URI toRedir;
  String toTitle;
  URI toUrl;
}

class Geo
{
  String city;
  String countryCode;
  String ispOrg;
  String latitude;
  String longitude;
  State state;
  String zip;
}

enum State
{
  MA, MN, NJ
}

class CamelCaseToLowerCaseWithUnderscoresNamingStrategy extends PropertyNamingStrategy
{
  @Override  
  public String nameForGetterMethod(MapperConfig<?> config,  
      AnnotatedMethod method, String defaultName)  
  {  
    return translate(defaultName);  
  }  

  @Override  
  public String nameForSetterMethod(MapperConfig<?> config,  
      AnnotatedMethod method, String defaultName)  
  {  
    return translate(defaultName);  
  }  

  @Override  
  public String nameForField(MapperConfig<?> config,  
      AnnotatedField field, String defaultName)  
  {  
    return translate(defaultName);  
  }  

  private String translate(String defaultName)  
  {  
    char[] nameChars = defaultName.toCharArray();  
    StringBuilder nameTranslated =  
        new StringBuilder(nameChars.length * 2);  
    for (char c : nameChars)  
    {  
      if (Character.isUpperCase(c))  
      {  
        nameTranslated.append("_");  
        c = Character.toLowerCase(c);  
      }  
      nameTranslated.append(c);  
    }  
    return nameTranslated.toString();  
  }
}

我也可以找出国家代码的枚举。

当然,这些字段实际上是私有的。

http://jira.codehaus.org/browse/JACKSON-598可以获得更完整的PropertyNamingStrategy

答案 1 :(得分:0)

根据您拥有“非Java”名称的类型数量,您可以实施Bruce建议的方法(对于大量类型可以很好地扩展);或者只是'手动'重命名,使用@JsonProperty注释将JSON值映射到Java属性。像这样:

public class Bean {
   @JsonProperty("NOTICE") public List<String> noticeTerms;
   public List<LinkObject> links;
}
public class LinkObject {
   @JsonProperty(""from_pubdate") public Date fromPublicationDate;
   // ...
}