001/* 002 * Copyright (c) 2009 The openGion Project. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 013 * either express or implied. See the License for the specific language 014 * governing permissions and limitations under the License. 015 */ 016package org.opengion.plugin.io; 017 018import java.io.PrintWriter; 019import java.util.List; 020import java.util.Locale; 021import java.util.Map ; 022import java.util.LinkedHashMap ; 023 024import org.opengion.fukurou.util.HybsEntry; 025import org.opengion.hayabusa.db.DBTableModel; 026 027/** 028 * TableWriter をJSON形式で出力する為の実装クラスです。 029 * DefaultTableWriter を継承していますので,ラベル,名前,データの出力部のみ 030 * オーバーライドして,JSON形式ファイルの出力機能を実現しています。 031 * 032 * 出力のJSON形式(JavaScript Object Notation)は、JavaScriptにおける 033 * オブジェクトの表記法をベースとした軽量なデータ記述言語です。 034 * このクラスでは、基本的にはすべてを文字列として処理しますので、 035 * 数字や、true,false も、ダブルコーテーションでくくることになります。 036 * ただし、null の場合は、null 表記になりますが、通常 空文字 "" になる場合もあります。 037 * 1レコードのみの場合でも、配列要素として取り扱います。 038 * UTF-8 でエンコードし、MIMEタイプはapplication/json、拡張子はjson とするのが一般的です。 039 * 040 * [ 041 * { "カラム1":"値1" , "カラム2":"値2" , … } , 1レコード目 042 * { "カラム1":"値1" , "カラム2":"値2" , … } , 2レコード目 043 * ・・・・ 044 * { "カラム1":"値1" , "カラム2":"値2" , … } Nレコード目 045 * ] 046 * 047 * writeTableParamタグで、key="JsonName" value="パラメータ名" を指定すると、 048 * JSON形式で、配列をオブジェクトとしてまとめるパラメータを指定する事が可能です。 049 * 050 * { 051 * パラメータ名:[ 052 * { "カラム1":"値1" , "カラム2":"値2" , … } , 1レコード目 053 * { "カラム1":"値1" , "カラム2":"値2" , … } , 2レコード目 054 * ・・・・ 055 * { "カラム1":"値1" , "カラム2":"値2" , … } Nレコード目 056 * ] 057 * } 058 * 059 * writeTableParamタグで、key="LowerCase" value="true" を指定すると、 060 * すべてのカラムを小文字で出力します。(データ受信側の都合を配慮) 061 * 初期値は、false なので、基本的に大文字になります。 062 * 063 * @og.rev 5.6.0.3 (2012/01/24) 新規作成 064 * @og.group ファイル出力 065 * 066 * @version 4.0 067 * @author Kazuhiko Hasegawa 068 * @since JDK5.0, 069 */ 070public class TableWriter_JSON extends TableWriter_Default { 071 //* このプログラムのVERSION文字列を設定します。 {@value} */ 072 private static final String VERSION = "5.6.6.1 (2013/07/12)" ; 073 074 // 5.6.6.1 (2013/07/12) keys の整合性チェックを行います。 075 private static final Map<String,String> keysMap = new LinkedHashMap<String,String>(); 076 077 static { 078 keysMap.put( "JSONNAME" , "JSON形式で、配列をオブジェクトとしてまとめる場合に使う" ); 079 keysMap.put( "LOWERCASE" , "カラム名(=パラメータ名)を小文字にする場合、true をセット(初期値:false)" ); 080 } 081 082 private String jsonName = null; // JSON形式で、配列をオブジェクトとしてまとめるパラメータを指定する場合に使う。 083 private boolean toLowerCase = false; // カラム名(=パラメータ名)を小文字にする場合、true にセットします。初期値は大文字のまま。 084 085 /** 086 * DBTableModel から データを作成して,PrintWriter に書き出します。 087 * 088 * @param writer PrintWriterオブジェクト 089 */ 090 @Override 091 public void writeDBTable( final PrintWriter writer ) { 092 super.setHeaderSequence( "D" ); 093 super.writeDBTable( writer ); 094 } 095 096 /** 097 * PrintWriter に DBTableModelのテーブル情報を書き込みます。 098 * 099 * 出力のXML形式は、ORACLE XDK での出力ファイルと同じ形式ですので、直接データベースに 100 * 登録することができます。 101 * 102 * @og.rev 5.6.0.3 (2012/01/24) JSON形式のフォーマットを作成します。 103 * @og.rev 5.6.1.2 (2013/02/22) jsonName もダブルクオートで囲う。 104 * 105 * @param table DBTableModelオブジェクト 106 * @param writer PrintWriterオブジェクト 107 */ 108 @Override 109 protected void writeData( final DBTableModel table,final PrintWriter writer ) { 110 int numberOfRows = table.getRowCount(); 111 112 String[] names = table.getNames(); 113 if( toLowerCase ) { 114 for( int i=0; i<names.length; i++ ) { 115// names[i] = names[i].toLowerCase(); 5.6.6.1 (2013/07/12) 116 names[i] = names[i].toLowerCase(Locale.JAPAN); 117 } 118 } 119 120 if( jsonName != null ) { 121 writer.println( "{" ); 122 writer.print( "\"" ); // 5.6.1.2 (2013/02/22) jsonName もダブルクオートで囲う。 123 writer.print( jsonName ); 124 writer.print( "\":" ); // 5.6.1.2 (2013/02/22) jsonName もダブルクオートで囲う。 125 } 126 127 writer.println( "[" ); 128 129 for( int row=0; row<numberOfRows; row++ ) { 130 if( row > 0 ) { writer.print( "," ); } // 最初以後の連結は、, を使う 131 writer.print( "{" ); 132 for( int i=0; i<numberOfColumns; i++ ) { 133 int clm = clmNo[i]; 134 String val = table.getValue(row,clm); 135 // \(バックスラッシュ) と "(ダブルクオート)のエスケープ 136 if( val.contains( "\\" ) || val.contains( "\"" ) ) { 137 StringBuilder sb = new StringBuilder(); 138 for( int j=0; j<val.length(); j++ ) { 139 char ch = val.charAt( j ); 140 if( ch == '\\' || ch == '\"' ) { sb.append( '\\' ); } 141 sb.append( ch ); 142 } 143 val = sb.toString(); 144 } 145 146 if( i > 0 ) { writer.print( "," ); } // 最初以後の連結は、, を使う 147 writer.print( '"' ); 148 writer.print( names[clm] ); 149 writer.print( "\":\"" ); 150 writer.print( val ); 151 writer.print( '"' ); 152 } 153 writer.println( "}" ); 154 } 155 156 writer.println( "]" ); 157 158 if( jsonName != null ) { 159 writer.println( "}" ); 160 } 161 } 162 163 /** 164 * パラメーターリストをセットします。 165 * JSONのパラメータ名を指定します。 166 * 引数が、null の場合は、何もしません。 167 * 168 * @og.rev 5.6.0.3 (2012/01/24) JSONのパラメータ名を指定します。 169 * @og.rev 5.6.6.1 (2013/07/12) keys の整合性チェックを行います。 170 * 171 * @param listParam HybsEntryリスト 172 */ 173 @Override 174 public void setParam( final List<HybsEntry> listParam ) { 175 if( listParam != null && ! listParam.isEmpty() ) { 176 for( HybsEntry entry : listParam ) { 177 String key = entry.getKey() ; // 5.6.6.1 (2013/07/12) keys の整合性チェック 178 checkParam( key , keysMap ); 179 180 String val = entry.getValue() ; // 5.6.6.1 (2013/07/12) val を先に取得 181 if( val != null && val.length() > 0 ) { 182 // JSON形式で、配列をオブジェクトとしてまとめるパラメータを指定する場合に使う。 183 if( "JsonName".equalsIgnoreCase( key ) ) { 184 jsonName = val ; 185 } 186 // カラム名(=パラメータ名)を小文字にする場合、true にセットします。初期値はfalse:大文字のまま。 187 else if( "LowerCase".equalsIgnoreCase( key ) ) { 188 toLowerCase = Boolean.parseBoolean( val ); 189 } 190 } 191 192// // JSON形式で、配列をオブジェクトとしてまとめるパラメータを指定する場合に使う。 193// if( "JsonName".equalsIgnoreCase( entry.getKey() ) ) { 194// jsonName = entry.getValue(); 195// } 196// // カラム名(=パラメータ名)を小文字にする場合、true にセットします。初期値は大文字のまま。 197// if( "LowerCase".equalsIgnoreCase( entry.getKey() ) ) { 198// toLowerCase = true; 199// } 200 } 201 } 202 } 203}