annotationでJson-libを補助してJavaBeanを変換します.


annotationでJson-libを補助してJavaBean<script type=「text/javascript」>



概要
今は多くのWebサイトでAJAX技術を応用しており、より少ないデータ通信を通じて、サーバーはユーザーの要求をより速くフィードバックし、更にJavascriptのコントロールを通じて、ユーザーにより良いユーザー体験をさせています.JSONは軽量級のデータ交換言語であり、Javascriptのサブセットであり、また優れた読み取り可能性があり、クライアントとサーバ間のデータ交換によく使われています.したがって、サーバ端では、エンティティオブジェクト(JavaBean)をJSONフォーマットデータに変換する必要がある場合が多い.本論文はJson-libを使ってJavaBenをJSON形式のデータに変換する方法を紹介し、解決方法を提供し、annotationを利用してJson-libを強化する2つの機能を紹介します.第二に、Json Value Processorを通じて、JavaBean属性をJSONデータに変換する方法を定義しています.
ページの端に戻る
JSONデータフォーマット
JSONのデータフォーマットは簡単で読みやすいです.二つの基本形式に存在します.
  • 名の値ペア:名前と値は‘:’で分けられます.名前のペア間を‘,’で区切る.全体を「{}」でくくります.例えば{name 1:value 1,name 2:value 2}
  • 値の順序付けられたキュー(Aray):すなわち配列、各値間を‘,’で区切る.全体を「[]」でくくります.例えば、[value 1,value 2]
  • この2つの形式の有機結合は,JSONデータを形成する.
    ページの端に戻る
    Json-libを使ってJavaBeanを変換してJSONデータにします。
    Json-libはJavaツールライブラリであり、apiを提供してJavaBean、Map、CollectionなどのオブジェクトをJSONデータに変換したり、逆にJSONデータを通じてJavaBenを得る.
    JSONSerializerのtoJSON法を使えば任意のJava ObjectをJSONオブジェクトに変換できます.JSONオブジェクトを呼び出すtoString方法で変換後の文字列が得られます.しかし、もう一つの問題は自分で解決しなければなりません.
    リスト1.JSONSerializerを使う
    import net.sf.json.JSONSerializer;
    
    List list = new ArrayList();  
    list.add( "first" );
    list.add( "second" );
    JSON json = JSONSerializer.toJSON( list );
    System.out.println( json.toString() );
    // prints ["first","second"]
    
    class MyBean{
        private String name = "json";
        private int pojoId = 1;
        
        // getters & setters
        ...
    }
    json = JSONSerializer.toJSON( new MyBean() );
    System.out.println( json.toString() );
    // prints {"name":"json","pojoId":1}
    
    問題1:選択のあるJavaBeanの中の属性を抽出する必要があります。
    リスト1の例の変換後のJSONデータにはJavaBeanの中の全ての属性が含まれていますが、私たちはしばしば選択されたJavaBeanの中の特定の属性を抽出する必要があります.たとえば:
  • は循環参照の属性をフィルタリングする必要があります.この点はJson-libはCycleDetection Strategyを提供して処理しますが、直接フィルタリングはもっと簡単です.
  • の異なる場合は、JavaBeanの一部の属性だけが必要です.例えばリストインターフェースはBeanのいくつかの重要な属性だけを表示する必要があり、詳細インターフェースはより多くのBeanの属性を表示する必要があります.
  • の異なるユーザ権限制限ユーザは、特定の属性データしか入手できない.
  • 問題2:特定の属性をカスタマイズするための変換方法が必要です。
    一般的なObjectタイプ(Long,Stringなど)では、json-libにはデフォルトの値変換処理がありますが、いくつかの特殊なタイプに対しては、カスタム方式で属性の値を変換したいです.たとえば:
  • はjava.util.Dateタイプに対して、直接時間列に変換したいです.「year」:「2010」、「montth」:「4」、「day」:「10」のような結果がほしいです.
  • よく使われているコードデータ(例えば、性別)は、定義時にIntegerかもしれません.
    Json-libはすでにいくつかインターフェースを残して、ユーザーにそのデフォルト行為を修正させました.次はどうやってアンノテーションを利用してJson-libに協力してこの二つの問題を解決するかを見てみます.
    annotationを使ってJavaBean属性を絞り込みます。
    JSONSerializerはtoJSONの重積載方法を提供しています.一つのパラメータJson Configを追加して、このパラメータによってJson-libのデフォルト方式をカスタマイズすることができます.
    リスト2.JSONSerializerをカスタマイズしたプロパティフィルタ
    import net.sf.json.JSONSerializer;
    import net.sf.json.JsonConfig;
    import net.sf.json.util.PropertyFilter;
    //        
    PropertyFilter filter = new PropertyFilter(
        public boolean apply(Object source, String name, Object value) {
            if ( name.equals( “pojoId” ) ) {
                return true;   //    true,            
            }
            return false;
        }
    );
    //        
    JsonConfig config = new JsonConfig();
    config.setJsonPropertyFilter( filter );
    
    System.out.println( JSONSerializer.toJSON( new MyBean(), config ) );
    // prints {"name":"json"}
    
    リスト2から見れば、Json-libはPropertyFilterのapply方法によって属性フィルタリングを行い、例のように、フィルタが必要な属性名を全部書き入れることができます.次はどうやってアンノテーションを利用すればもっと便利な処理ができるかを見てみましょう.
    まず、annotationを定義し、MyBeaビンのget方法に表示する必要があります.
    リスト3.annotationを定義する:Invisible
    import java.lang.annotation.Target;
    import java.lang.annotation.Documented;
    import java.lang.annotation.Retention;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.RetentionPolicy;
    
    @Documented
    @Target({ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Invisible {
        public String[] value();
    }
    
    //  myBean        get  (  is  )  Invisible  
    public class MyBean{
        private String name = "json";
        private int pojoId = 1;
        
        // getters & setters
        public String getName() { return name; }
        @Invisible(“LIST”)   //   “LIST”          
        public int getPojoId() { return pojoId; }
    }
    
    それから、annotationを扱うPropertyFilter類が必要です.
    明細書4.annotationを扱うPropertyFilter類
    import java.util.Map;
    import java.lang.reflect.Method;
    import net.sf.json.util.PropertyFilter;
    //      abstract ,   Bean   Method          
    public abstract class AbstractMethodFilter implements PropertyFilter {
        //           ,           
        public abstract boolean apply(final Method method);
    
        public boolean apply(final Object source, final String name, final Object value) {
            if (source instanceof Map) {
                return false;
            }
            String propName = name.substring(0, 1).toUpperCase() + name.substring(1);
            Class clz = source.getClass();
            String methodName = "get" + propName;
            Method method = null;
            try {
                method = clz.getMethod(methodName, (Class[]) null);   //      get  
            } catch (NoSuchMethodException nsme) {
                String methodName2 =  "is" + propName;                //     is  
                try {
                    method = clz.getMethod(methodName2, (Class[]) null);
                } catch (NoSuchMethodException ne) {
                    //        get  is  ,    ,  true
                    System.err.println(“No such methods: ” 
    					+ methodName + “ or “ + methodName2);
                    return true;
                }
            }
            return apply(method);
        }
    } // END: AbstractMethodFilter
    
    public class InvisibleFilter extends AbstractMethodFilter {
        //     ,           property     
        private String _sGUIID;
        public InvisibleFilter(final String guiid) {
            _sGUIID = guiid;
        }
    
        public boolean apply(final Method method) {
            if (_sGUIID == null || _sGUIID.equals(“”)) {
                return false;                                         //       
            }
            if (method.isAnnotationPresent(Invisible.class)) {
                Invisible anno = method.getAnnotation(Invisible.class);
                String[] value = anno.value();
                for (int i = 0; i < value.length; i++) {
                    if (_sGUIID.equals(value[i])) {
                        return true;
                    }
                }
            }
            return false;
        }
    }
    
    今はこのfilterをJson Configに登録するだけで、属性のフィルタリングができます.単5を確認してください.
    リスト5.Invisible Filterを使って不要な属性をフィルタリングする
    JsonConfig config = new JsonConfig();
    config.setJsonPropertyFilter( new InvisibleFilter(“LIST”)); //   LIST        
    
    System.out.println( JSONSerializer.toJSON( new MyBean(), config ) );
    // prints {"name":"json"}
    
    他のannotationとFilterを追加すれば、異なる属性フィルタリング方式が実現できます.
    annotationを使ってビーン属性の変換方式をカスタマイズします。
    Json-libは、Json Configを通じて、独自の属性変換方式のインターフェースを提供しています.
    明細書6.Json Value Processorを登録する
    JsonConfig config = new JsonConfig();
    config.registerJsonValueProcessor(java.util.Date.class, new JsDateJsonValueProcessor());
    
    登録後Json-libはjava.uitl.Dateタイプの属性に遭遇した時、JsDateJson ValueProcessorの処理方法を適用します.
    だから、自分のJson Value Processorを実現すれば、各種Objectの変換方式をカスタマイズすることができます.
    前節の議論によれば、Json-libはBean属性を変換する前に、プロパティデータをProptyFilterに伝達して、フィルタリングが必要かどうかを判断します.したがって、Filterオブジェクトを通して、Benの属性の表示データを取得し、特定のProcessorに渡すことができます.Processorは、得られた表示値に基づいて、この属性をどのように扱うべきかを知ることができます.整理コードを例にとって、処理の方法を説明します.
    一般的には、一つの項目には多くの異なるコードが含まれています.それぞれのコードにマスターコード番号を定義します.そのサブコードにはいくつかのサブコード番号が定義されます.例えば、私たちは性別の主なコード番号を100と定義し、男性を1,女性を2と定義します.
    まず、コード表示(IntegerCode)とこの表示を扱うProptyFilterが必要です.
    明細書7.IntegerCodeおよびInteger CodeFilter
    @Documented
    @Target({ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface IntegerCode {
        public int value();
    }
    
    public class IntegerCodeFilter extends AbstractMethodFilter {
        //      
        private IntegerCodeProcessor _processor;
        public IntegerCodeFilter(final IntegerCodeProcessor processor) {
            _processor = processor;
        }
    
        //      ,    IntegerCode   ,      Processor
        public boolean apply(final Method method) {
            if (_processor == null) {
                return false;                                //          
            }
            if (method.isAnnotationPresent(IntegerCode.class)) {
                IntegerCode anno = method.getAnnotation(IntegerCode.class);
                int code = anno.value();
                _processor.setMainCode(code);                //  code      
            }
            return false;
        }
    }
    
    今、私たちはIntegerCodeのデータを処理するためにJson Value Processorが必要です.
    リスト8.Integer CodeProcessor
    public class IntegerCodeProcessor implements JsonValueProcessor {
    
        private int _iMainCode;
    
        public void setMainCode(final int mainCode) { _iMainCode = mainCode; }
    
        public IntegerCodeProcessor() {
            super();
        } // END: IntegerCodeProcessor
    
        private void reset() {
            _iMainCode = -1;
        }
    
        public Object processArrayValue(Object value, JsonConfig jsonConfig) {
            return process(value, jsonConfig);
        } // END: processArrayValue
    
        public Object processObjectValue(
                String key, Object value, JsonConfig jsonConfig ) {
            return process( value, jsonConfig );
        } // END: processObjectValue
    
        private Object process(Object value, JsonConfig jsonConfig) {
            if (value == null) {
                return null;
            }
            String ret = null;
            if (value instanceof Integer && _iMainCode >= 0) {
                int code = value.intValue();
                switch (_iMainCode) {
                    case 100:                    //        case        
                        if (code == 1) {         //                   
                            ret = "man";
                        } else if (code == 2) {
                            ret = "woman";
                        } else {
                            ret = value.toString();
                        }
                        break;
                    default:
                        ret = value.toString();
                        break;
                }
            } else {
                ret = value.toString();
            }
            reset();                             //      ,       Integer   
    
            return ret;
        } // END: process
    }
    
    今、私たちはJavaBeanを作成します.StudentはこのProcessorをテストします.
    明細書9.Integer CodeProcessorをテストする
    public class Student {
        private String name = "camry";
        private int gender = 1;
        
        // getters & setters
        public String getName() { return name; }
        @IntegerCode(100)                              //        100
        public int getGender() { return gender; }}
    }
    
    ...
    IntegerCodeProcessor processor = new IntegerCodeProcessor();
    IntegerCodeFilter filter = new IntegerCodeFilter(processor);
    JsonConfig config = new JsonConfig();
    config.setJsonPropertyFilter( filter );
    config.registerJsonValueProcessor(Integer.class, processor);
    
    System.out.println( JSONSerializer.toJSON( new Student(), config ) );
    // prints {“gender”:”man”, "name":"camry"}
    
    Json-libはJavaBeanからJSONまでのデータの変換を簡単に行うことができます.annotationと関連してJavaBeanの属性にメタデータを定義します.コードを減少させ、効率を向上させます.CMA ID:500805--