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 = "6.0.1.2 (2014/08/08)" ; 073 074 // 5.6.6.1 (2013/07/12) keys の整合性チェックを行います。 075 private static final Map<String,String> keysMap = new LinkedHashMap<String,String>(); 076 077 private String jsonName = null; // JSON形式で、配列をオブジェクトとしてまとめるパラメータを指定する場合に使う。 078 private boolean toLowerCase = false; // カラム名(=パラメータ名)を小文字にする場合、true にセットします。初期値は大文字のまま。 079 080 static { 081 keysMap.put( "JSONNAME" , "JSON形式で、配列をオブジェクトとしてまとめる場合に使う" ); 082 keysMap.put( "LOWERCASE" , "カラム名(=パラメータ名)を小文字にする場合、true をセット(初期値:false)" ); 083 } 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 * @og.rev 6.0.1.2 (2014/08/08) カラム飛ばしできる機能を追加 105 * 106 * @param table DBTableModelオブジェクト 107 * @param writer PrintWriterオブジェクト 108 */ 109 @Override 110 protected void writeData( final DBTableModel table,final PrintWriter writer ) { 111 int numberOfRows = table.getRowCount(); 112 113 String[] names = table.getNames(); 114 if( toLowerCase ) { 115 for( int i=0; i<names.length; i++ ) { 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 if( i > 0 ) { writer.print( "," ); } // 最初以後の連結は、, を使う 134 int clm = clmNo[i]; 135 if( clm < 0 ) { continue; } // 6.0.1.2 (2014/08/08) カラム飛ばし 136 137 String val = table.getValue(row,clm); 138 // \(バックスラッシュ) と "(ダブルクオート)のエスケープ 139 if( val.contains( "\\" ) || val.contains( "\"" ) ) { 140 StringBuilder sb = new StringBuilder(); 141 for( int j=0; j<val.length(); j++ ) { 142 char ch = val.charAt( j ); 143 if( ch == '\\' || ch == '\"' ) { sb.append( '\\' ); } 144 sb.append( ch ); 145 } 146 val = sb.toString(); 147 } 148 149 writer.print( '"' ); 150 writer.print( names[clm] ); 151 writer.print( "\":\"" ); 152 writer.print( val ); 153 writer.print( '"' ); 154 } 155 writer.println( "}" ); 156 } 157 158 writer.println( "]" ); 159 160 if( jsonName != null ) { 161 writer.println( "}" ); 162 } 163 } 164 165 /** 166 * パラメーターリストをセットします。 167 * JSONのパラメータ名を指定します。 168 * 引数が、null の場合は、何もしません。 169 * 170 * @og.rev 5.6.0.3 (2012/01/24) JSONのパラメータ名を指定します。 171 * @og.rev 5.6.6.1 (2013/07/12) keys の整合性チェックを行います。 172 * 173 * @param listParam HybsEntryリスト 174 */ 175 @Override 176 public void setParam( final List<HybsEntry> listParam ) { 177 if( listParam != null && ! listParam.isEmpty() ) { 178 for( HybsEntry entry : listParam ) { 179 String key = entry.getKey() ; // 5.6.6.1 (2013/07/12) keys の整合性チェック 180 checkParam( key , keysMap ); 181 182 String val = entry.getValue() ; // 5.6.6.1 (2013/07/12) val を先に取得 183 if( val != null && val.length() > 0 ) { 184 // JSON形式で、配列をオブジェクトとしてまとめるパラメータを指定する場合に使う。 185 if( "JsonName".equalsIgnoreCase( key ) ) { 186 jsonName = val ; 187 } 188 // カラム名(=パラメータ名)を小文字にする場合、true にセットします。初期値はfalse:大文字のまま。 189 else if( "LowerCase".equalsIgnoreCase( key ) ) { 190 toLowerCase = Boolean.parseBoolean( val ); 191 } 192 } 193 } 194 } 195 } 196}