4

次のように列挙型が定義されていると想像してください。

public enum ArchiveStatus implements Serializable {
  CANDIDATE         (0, "CANDIDATE", "Candidate for archival"),
  IN_LIBRARY          (1, "IN-LIBRARY", ".."),
  FROM_LIBRARY        (2, "FROM-LIBRARY", "..");

  private int id;
  private String shortName;
  private String longName;

  public ArchiveStatus( int id, String shortName, String longName ) {
    ..
  }

  public int getId() { .. }
  public String getShortName() { .. }
  public String getLongName() { .. }
}

デフォルトでは、MOXy は次のように JSON にシリアライズします。

{
   ..
   "archiveStatus": "CANDIDATE",
   ..
}

MOXy (マッピング ファイル内) を構成して、通常のクラスのように列挙型をシリアル化する方法はありますか。

{
   ..
   "archiveStatus": { "id" : 0, "shortName": "CANDIDATE", "longName": "Candidate for archival" },
   ..
}
4

1 に答える 1

4

注: 私はEclipseLink JAXB (MOXy)のリーダーであり、JAXB 2 (JSR-222)エキスパート グループのメンバーです。

ArchiveStatusAdapter

を活用することで、このユース ケースを解決できますXmlAdapterXmlAdapterあるタイプのオブジェクトを別のタイプのオブジェクトとしてマーシャリングできるようにする JAXB メカニズムです。

package forum10144489;

import javax.xml.bind.annotation.adapters.XmlAdapter;

public class ArchiveStatusAdapter extends XmlAdapter<ArchiveStatusAdapter.AdaptedArchiveStatus, ArchiveStatus> {

    public static class AdaptedArchiveStatus {
        public int id;
        public String shortName;
        public String longName;
    }

    @Override
    public ArchiveStatus unmarshal(AdaptedArchiveStatus adaptedArchiveStatus) throws Exception {
        if(null == adaptedArchiveStatus) {
            return null;
        }
        return ArchiveStatus.valueOf(adaptedArchiveStatus.shortName);
    }

    @Override
    public AdaptedArchiveStatus marshal(ArchiveStatus archiveStatus) throws Exception {
        if(null == archiveStatus) {
            return null;
        }
        AdaptedArchiveStatus adaptedArchiveStatus = new AdaptedArchiveStatus();
        adaptedArchiveStatus.id = archiveStatus.getId();
        adaptedArchiveStatus.longName = archiveStatus.getLongName();
        adaptedArchiveStatus.shortName = archiveStatus.getShortName();
        return adaptedArchiveStatus;
    }

}

注釈XmlAdapterを使用して、フィールド、プロパティ、型、またはパッケージ レベルで指定できます。@XmlJavaTypeAdapter

package forum10144489;

import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

public class Root {

    private ArchiveStatus archiveStatus;

    @XmlJavaTypeAdapter(ArchiveStatusAdapter.class)
    public ArchiveStatus getArchiveStatus() {
        return archiveStatus;
    }

    public void setArchiveStatus(ArchiveStatus archiveStatus) {
        this.archiveStatus = archiveStatus;
    }

}

jaxb.properties

MOXy を JAXB プロバイダーとして指定するにjaxb.propertiesは、次のエントリを使用して、ドメイン クラスと同じパッケージで呼び出されるファイルを追加する必要があります。

javax.xml.bind.context.factory = org.eclipse.persistence.jaxb.JAXBContextFactory

デモ

package forum10144489;

import java.io.StringReader;
import java.util.*;
import javax.xml.bind.*;
import javax.xml.transform.stream.StreamSource;

public class Demo {

    public static void main(String[] args) throws Exception {
        Map<String, Object> properties = new HashMap<String, Object>(2);
        properties.put("eclipselink.media-type", "application/json");
        properties.put("eclipselink.json.include-root", false);
        JAXBContext jc = JAXBContext.newInstance(new Class[] {Root.class}, properties);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        StringReader jsonStringReader = new StringReader("{\"archiveStatus\" : {\"id\" : 0, \"shortName\" : \"CANDIDATE\", \"longName\" : \"Candidate for archival\"}}");
        StreamSource jsonSource = new StreamSource(jsonStringReader);
        Root root = unmarshaller.unmarshal(jsonSource, Root.class).getValue();

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(root, System.out);
    }

}

出力

以下は、デモ コードを実行した結果の出力です。

{
   "archiveStatus" : {
      "id" : 0,
      "shortName" : "CANDIDATE",
      "longName" : "Candidate for archival"
   }
}

詳細については

于 2012-04-16T15:53:45.343 に答える