как создать элементы данных для bean-компонента, которые будут использоваться для анализа данных JSON с использованием анализатора Джексона (или аналогичного) - PullRequest
0 голосов
/ 15 июля 2011

Я прочитал некоторые учебники, в которых говорится, что простой bean-компонент должен быть определен с помощью методов getter и setter, представляющих данные JSON систематическим образом.

Ниже приводятся данные, которые мне придется анализировать, чтобы помочь мне, определив компонент для ситуации такого типа (где один узел содержит много узлов, каждый из которых содержит отдельные подчиненные узлы)

Мне требуются from_title, from_url, to_title и to_url для примерно 2500 записей из вывода JSON.

---------------- ОБРАЗЕЦ ДАННЫХ JSON ----------------------------

{
"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 ]

2 голосов
/ 15 июля 2011

Вот что я бы сделал.

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();  
  }
}

Я также могу определить перечисление для кодов стран.

Конечно, поля на самом деле будут частными.

Более полная PropertyNamingStrategy доступна по адресу http://jira.codehaus.org/browse/JACKSON-598.

0 голосов
/ 16 июля 2011

В зависимости от того, сколько типов с именами «не-Java» у вас есть, вы можете реализовать подход, который рекомендует Брюс (который отлично подходит для большого количества типов);или просто «вручную» переименовать вещи, используя аннотации @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;
   // ...
}
...