0

我有一个令人费解的 RESTful 问题。我使用使用 POJO 映射将 Java 对象(Beans?)转换为 JSON 的 Jersey 使用 REST。最初这很好用,但是现在,在尝试向 Bean 添加新字段时,它们不会出现在客户端接收的 JSON 中。稍后我将进一步解释我的意思,但首先让我展示一些代码。

控制器代码在这里(经过编辑以简化它......基本部分仍然存在):

@Path( "study" )
public class StudyQueryController 
{
    @Path( "/query" )
    @GET
    @Produces( { MediaType.APPLICATION_JSON } )
    public List< PatientBean > queryForStudies(
            @QueryParam( "keyword" ) String keyword,
            @QueryParam( "fromDate" ) String fromDate,
            @QueryParam( "toDate" ) String toDate,
            @QueryParam( "sites" ) Set< Integer > sites,
            @DefaultValue( CLOUD_STYPE ) @QueryParam( "stypes" ) Set< Integer > stypes,
            @DefaultValue( "false" ) @QueryParam( "incDeleted" ) boolean incDeleted )
    {
        UserModel user = AuthFilter.requestingUser;

        try ( KHDatabase khdb = new KHDatabase() )
        {
               [... code is here that sets up the queries, keys, etc...]

            CommonQueries.PSSTree tree = CommonQueries.getPatientStudySeriesTree( khdb, keys );
            List< PatientBean > ret = PatientBean.mapPSSTree( tree );

            return ret;
        }
        catch (SQLException e)
        {
            [...throws error here...]
        }
    }
}

请注意,返回了一个由 PatientBean 对象组成的 List。PatientBean 代码在这里:

public class PatientBean {

    private String patientName;
    private String patientBleah;
    private String patientID;
    private String patientSex;
    private String patientDOB;
    private int patientSite;
    private String siteName;
    private StudyBean[] studies;

//  public String getPatientName() {
//      return patientName;
//  }
    public String getPatientBleah() {       // TEST
        return patientBleah;
    }
    public String getPatientID() {
        return patientID;
    }
    public String getPatientSex() {
        return patientSex;
    }
    public String getPatientDOB() {
        return patientDOB;
    }
    public int getPatientSite() {
        return patientSite;
    }
    public void setSiteName(String newName) {
        siteName = newName;
    }
    public String getSiteName() {
        return siteName;
    }
    public StudyBean[] getStudies() {
        return studies;
    }

    /** Maps a <code>KHPatient</code>, its collection of <code>KHStudy</code>, and the map of
     *  study keys to lists of <code>KHSeries</code> of the studies, to an instance of this class. */
    public PatientBean( KHPatient pt, List< KHStudy > sts, Map< String, List< KHSeries > > srs  )
    {
        patientName = pt.getFullName().toDICOMPN();
        patientBleah = pt.getFullName().toDICOMPN();
        patientID = pt.id;
        patientSex = Character.toString( pt.sex.getDICOMCode() );
        patientDOB = pt.birthdate != null ? StringUtils.printISODate( pt.birthdate ) : "";
        patientSite = pt.site_key;


        List< StudyBean > lst = new ArrayList< StudyBean >( sts.size() );
        for ( KHStudy st : sts )
        {
            List< KHSeries > lsr = srs.get( st.key() );
            if ( lsr == null )
                lsr = Collections.emptyList();
            lst.add( new StudyBean( st, lsr ) );
        }
        studies = lst.toArray( new StudyBean[ lst.size() ] );
    }

    /** Maps a <code>CommonQueries.PSSTree</code> to an array of {@link PatientBean}. */
    public static List< PatientBean > mapPSSTree( CommonQueries.PSSTree tree )
    {
        List< PatientBean > lpt = new ArrayList< PatientBean >( tree.pts.size() );
        for ( Map.Entry< Integer, KHPatient > entry : tree.pts.entrySet() )
        {
            KHPatient pt = entry.getValue();
            List< KHStudy > lst = tree.sts.get( entry.getKey() );
            PatientBean bpt = new PatientBean( pt, lst, tree.srs );
            lpt.add( bpt );
        }
        return lpt;
    }
}

大部分字段,例如 patientName、patientID、patientSEX、patientDOB 和 patientSite 都是该 Bean 原始版本的一部分,并且可以通过 JSON 返回。不会返回新字段,例如 patientBleah 和 siteName。

为了确保这个文件确实被 maven 重新编译,我尝试注释掉 getPatientName() 方法。正如预期的那样,这导致客户端为患者姓名获得“未定义”。但是,patientBleah 和 siteName 根本不会出现在客户端 JSON 中。

我一生都不知道为什么注释掉 getPatientName() 有效果,而添加其他字段(和相应的 getter 方法)没有效果。

我对 RESTful 服务和 POJO 比较陌生,所以也许我遗漏了一些明显的东西。我的印象是 POJO 映射只需要一个具有字段和相应公共 getter 方法的类,其余的由它完成。

来自服务器的 web.xml 的片段,以防这也有帮助:

  <servlet>
    <servlet-name>AimCloudREST</servlet-name>
    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
    <init-param>
      <param-name>com.sun.jersey.config.property.packages</param-name>
      <param-value>com.aimcloud.server;com.aimcloud.util</param-value>
    </init-param>
    <init-param>
      <param-name>com.sun.jersey.spi.container.ContainerRequestFilters</param-name>
      <param-value>com.aimcloud.util.AuthFilter</param-value>
    </init-param>
    <init-param>
      <param-name>com.sun.jersey.spi.container.ContainerResponseFilters</param-name>
      <param-value>com.aimcloud.util.ErrorFilter;com.aimcloud.util.AuthFilter</param-value>
    </init-param>
    <init-param>
      <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
      <param-value>true</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>

我确实尝试使用“mvn clean package”进行编译,但这没有帮助。我还尝试在重新编译后停止并重新启动 tomcat。

4

1 回答 1

0

我发现问题是发送到客户端的 JSON 响应以未命名数组开始。换句话说,它看起来像这样:

[{"patients":[{"patientName":"ASHA01^^^^==","patientBleah":"ASHA01^^^^==",[...],"patientSite":1}]

JavaScript 没有正确解析它。数组必须命名,如下所示:

{"myArray":[...]}

我将其追溯到 RESTful Jersey 代码中的这一行:

List< PatientBean > ret = PatientBean.mapPSSTree( tree );

这个“ret”对象是返回给用户的。这就是导致未命名数组作为 JSON 返回的原因,JavaScript 无法正确解析该数组。(尽管被http://www.jsoneditoronline.org/正确解析)

这里的解决方案是将我的结果包装在一个具有单个元素的更高级别的对象中:List。然后我返回这个对象,然后我的数组有一个名称,生成的 JSON 被正确解释。

public class ResultBean {

    private List< PatientBean > patients;

    public List< PatientBean > getPatients() {
        return patients;
    }

    public ResultBean( List< PatientBean > inPatients )
    {
        patients = inPatients;
    }
}
于 2013-08-01T01:10:40.727 回答