version 2.1.364 (October 15 2009)
If you like this script, please donate to keep development active!
JavaScript code syntax highlighter.
Copyright 2004-2009 Alex Gorbatchev.

'},debug:false},vars:{discoveredBrushes:null,spaceWidth:null,printFrame:null,highlighters:{}},brushes:{},regexLib:{multiLineCComments:/\/\*[\s\S]*?\*\//gm,singleLineCComments:/\/\/.*$/gm,singleLinePerlComments:/#.*$/gm,doubleQuotedString:/"([^\\"\n]|\\.)*"/g,singleQuotedString:/'([^\\'\n]|\\.)*'/g,multiLineDoubleQuotedString:/"([^\\"]|\\.)*"/g,multiLineSingleQuotedString:/'([^\\']|\\.)*'/g,xmlComments:/(<|<)!--[\s\S]*?--(>|>)/gm,url:/<\w+:\/\/[\w-.\/?%&=@:;]*>|\w+:\/\/[\w-.\/?%&=@:;]*/g,phpScriptTags:{left:/(<|<)\?=?/g,right:/\?(>|>)/g},aspScriptTags:{left:/(<|<)%=?/g,right:/%(>|>)/g},scriptScriptTags:{left:/(<|<)\s*script.*?(>|>)/gi,right:/(<|<)\/\s*script\s*(>|>)/gi}},toolbar:{create:function(highlighter){var div=document.createElement("DIV"),items=sh.toolbar.items;div.className="toolbar";for(var name in items){var constructor=items[name],command=new constructor(highlighter),element=command.create();highlighter.toolbarCommands[name]=command;if(element==null){continue}if(typeof(element)=="string"){element=sh.toolbar.createButton(element,highlighter.id,name)}element.className+="item "+name;div.appendChild(element)}return div},createButton:function(label,highlighterId,commandName){var a=document.createElement("a"),style=a.style,config=sh.config,width=config.toolbarItemWidth,height=config.toolbarItemHeight;a.href="#"+commandName;a.title=label;a.highlighterId=highlighterId;a.commandName=commandName;a.innerHTML=label;if(isNaN(width)==false){style.width=width+"px"}if(isNaN(height)==false){style.height=height+"px"}a.onclick=function(e){try{sh.toolbar.executeCommand(this,e||window.event,this.highlighterId,this.commandName)}catch(e){sh.utils.alert(e.message)}return false};return a},executeCommand:function(sender,event,highlighterId,commandName,args){var highlighter=sh.vars.highlighters[highlighterId],command;if(highlighter==null||(command=highlighter.toolbarCommands[commandName])==null){return null}return command.execute(sender,event,args)},items:{expandSource:function(highlighter){this.create=function(){if(highlighter.getParam("collapse")!=true){return}return sh.config.strings.expandSource};this.execute=function(sender,event,args){var div=highlighter.div;sender.parentNode.removeChild(sender);div.className=div.className.replace("collapsed","")}},viewSource:function(highlighter){this.create=function(){return sh.config.strings.viewSource};this.execute=function(sender,event,args){var code=sh.utils.fixInputString(highlighter.originalCode).replace(/"+code+"");wnd.document.close()}},copyToClipboard:function(highlighter){var flashDiv,flashSwf,highlighterId=highlighter.id;this.create=function(){var config=sh.config;if(config.clipboardSwf==null){return null}function params(list){var result="";for(var name in list){result+=""}return result}function attributes(list){var result="";for(var name in list){result+=" "+name+"='"+list[name]+"'"}return result}var args1={width:config.toolbarItemWidth,height:config.toolbarItemHeight,id:highlighterId+"_clipboard",type:"application/x-shockwave-flash",title:sh.config.strings.copyToClipboard},args2={allowScriptAccess:"always",wmode:"transparent",flashVars:"highlighterId="+highlighterId,menu:"false"},swf=config.clipboardSwf,html;if(/msie/i.test(navigator.userAgent)){html=""+params(args2)+params({movie:swf})+""}else{html=""}flashDiv=document.createElement("div");flashDiv.innerHTML=html;return flashDiv};this.execute=function(sender,event,args){var command=args.command;switch(command){case"get":var code=sh.utils.unindent(sh.utils.fixInputString(highlighter.originalCode).replace(//g,">").replace(/&/g,"&"));if(window.clipboardData){window.clipboardData.setData("text",code)}else{return sh.utils.unindent(code)}case"ok":sh.utils.alert(sh.config.strings.copyToClipboardConfirmation);break;case"error":sh.utils.alert(args.message);break}}},printSource:function(highlighter){this.create=function(){return sh.config.strings.print};this.execute=function(sender,event,args){var iframe=document.createElement("IFRAME"),doc=null;if(sh.vars.printFrame!=null){document.body.removeChild(sh.vars.printFrame)}sh.vars.printFrame=iframe;iframe.style.cssText="position:absolute;width:0px;height:0px;left:-500px;top:-500px;";document.body.appendChild(iframe);doc=iframe.contentWindow.document;copyStyles(doc,window.document);doc.write('

'+highlighter.div.innerHTML+"

");doc.close();iframe.contentWindow.focus();iframe.contentWindow.print();function copyStyles(destDoc,sourceDoc){var links=sourceDoc.getElementsByTagName("link");for(var i=0;i')}}}}},about:function(highlighter){this.create=function(){return sh.config.strings.help};this.execute=function(sender,event){var wnd=sh.utils.popup("","_blank",500,250,"scrollbars=0"),doc=wnd.document;doc.write(sh.config.strings.aboutDialog);doc.close();wnd.focus()}}}},utils:{indexOf:function(array,searchElement,fromIndex){fromIndex=Math.max(fromIndex||0,0);for(var i=fromIndex;i(.*?))\\]$"),regex=new XRegExp("(?[\\w-]+)\\s*:\\s*(?[\\w-%#]+|\\[.*?\\]|\".*?\"|'.*?')\\s*;?","g");while((match=regex.exec(str))!=null){var value=match.value.replace(/^['"]|['"]$/g,"");if(value!=null&&arrayRegex.test(value)){var m=arrayRegex.exec(value);value=m.values.length>0?m.values.split(/\s*,\s*/):[]}result[match.name]=value}return result},decorate:function(str,css){if(str==null||str.length==0||str=="\n"){return str}str=str.replace(/'+line+""})}return str},padNumber:function(number,length){var result=number.toString();while(result.length",closeSpan="";container.innerHTML=divOpen+'syntaxhighlighter">'+divOpen+'lines">'+divOpen+'line">'+divOpen+'content"> '+closeSpan+closeSpan+closeDiv+closeDiv+closeDiv+closeDiv;body.appendChild(container);span=document.getElementById(id);if(/opera/i.test(navigator.userAgent)){var style=window.getComputedStyle(span,null);result=parseInt(style.getPropertyValue("width"))}else{result=span.offsetWidth}body.removeChild(container);return result},processTabs:function(code,tabSize){var tab="";for(var i=0;i|
/gi;if(sh.config.bloggerMode==true){str=str.replace(br,"\n")}if(sh.config.stripBrs==true){str=str.replace(br,"")}return str},trim:function(str){return str.replace(/^\s+|\s+$/g,"")},unindent:function(str){var lines=sh.utils.fixInputString(str).split("\n"),indents=new Array(),regex=/^\s*/,min=1000;for(var i=0;i0;i++){var line=lines[i];if(sh.utils.trim(line).length==0){continue}var matches=regex.exec(line);if(matches==null){return str}min=Math.min(matches[0].length,min)}if(min>0){for(var i=0;im2.index){return 1}else{if(m1.lengthm2.length){return 1}}}}return 0},getMatches:function(code,regexInfo){function defaultAdd(match,regexInfo){return[new sh.Match(match[0],match.index,regexInfo.css)]}var index=0,match=null,result=[],func=regexInfo.func?regexInfo.func:defaultAdd;while((match=regexInfo.regex.exec(code))!=null){result=result.concat(func(match,regexInfo))}return result},processUrls:function(code){var lt="<",gt=">";return code.replace(sh.regexLib.url,function(m){var suffix="",prefix="";if(m.indexOf(lt)==0){prefix=lt;m=m.substring(lt.length)}if(m.indexOf(gt)==m.length-gt.length){m=m.substring(0,m.length-gt.length);suffix=gt}return prefix+''+m+""+suffix})},getSyntaxHighlighterScriptTags:function(){var tags=document.getElementsByTagName("script"),result=[];for(var i=0;i",copy=sh.utils.trim(original),changed=false;if(copy.indexOf(left)==0){copy=copy.substring(left.length);changed=true}if(copy.indexOf(right)==copy.length-right.length){copy=copy.substring(0,copy.length-right.length);changed=true}return changed?copy:original}},highlight:function(globalParams,element){function toArray(source){var result=[];for(var i=0;iitemIEndPos){break}else{if(itemJ.index==itemI.index&&itemJ.length>itemI.length){this.matches[i]=null}else{if(itemJ.index>=itemI.index&&itemJ.index

'+(hasGutter?'":"")+'
'+lineNumber+"'+(spaces!=null?''+spaces.replace(" "," ")+"":"")+line+"
"}return code},processMatches:function(code,matches){var pos=0,result="",decorate=sh.utils.decorate,brushName=this.getParam("brush-name","");function getBrushNameCss(match){var result=match?(match.brushName||brushName):brushName;return result?result+" ":""}for(var i=0;i"+regexGroup.left.source+")(?.*?)(?"+regexGroup.right.source+")","sgi")}}};return sh}()}if(!window.XRegExp){(function(){var real={exec:RegExp.prototype.exec,match:String.prototype.match,replace:String.prototype.replace,split:String.prototype.split},lib={part:/(?:[^\\([#\s.]+|\\(?!k<[\w$]+>|[pP]{[^}]+})[\S\s]?|\((?=\?(?!#|<[\w$]+>)))+|(\()(?:\?(?:(#)[^)]*\)|<([$\w]+)>))?|\\(?:k<([\w$]+)>|[pP]{([^}]+)})|(\[\^?)|([\S\s])/g,replaceVar:/(?:[^$]+|\$(?![1-9$&`']|{[$\w]+}))+|\$(?:([1-9]\d*|[$&`'])|{([$\w]+)})/g,extended:/^(?:\s+|#.*)+/,quantifier:/^(?:[?*+]|{\d+(?:,\d*)?})/,classLeft:/&&\[\^?/g,classRight:/]/g},indexOf=function(array,item,from){for(var i=from||0;i-1,extended=flags.indexOf("x")>-1,hasNamedCapture=false,captureNames=[],output=[],part=lib.part,match,cc,len,index,regex;part.lastIndex=0;while(match=real.exec.call(part,pattern)){if(match[2]){if(!lib.quantifier.test(pattern.slice(part.lastIndex))){output.push("(?:)")}}else{if(match[1]){captureNames.push(match[3]||null);if(match[3]){hasNamedCapture=true}output.push("(")}else{if(match[4]){index=indexOf(captureNames,match[4]);output.push(index>-1?"\\"+(index+1)+(isNaN(pattern.charAt(part.lastIndex))?"":"(?:)"):match[0])}else{if(match[5]){output.push(plugins.unicode?plugins.unicode.get(match[5],match[0].charAt(1)==="P"):match[0])}else{if(match[6]){if(pattern.charAt(part.lastIndex)==="]"){output.push(match[6]==="["?"(?!)":"[\\S\\s]");part.lastIndex++}else{cc=XRegExp.matchRecursive("&&"+pattern.slice(match.index),lib.classLeft,lib.classRight,"",{escapeChar:"\\"})[0];output.push(match[6]+cc+"]");part.lastIndex+=cc.length+1}}else{if(match[7]){if(singleline&&match[7]==="."){output.push("[\\S\\s]")}else{if(extended&&lib.extended.test(match[7])){len=real.exec.call(lib.extended,pattern.slice(part.lastIndex-1))[0].length;if(!lib.quantifier.test(pattern.slice(part.lastIndex-1+len))){output.push("(?:)")}part.lastIndex+=len-1}else{output.push(match[7])}}}else{output.push(match[0])}}}}}}}regex=RegExp(output.join(""),real.replace.call(flags,/[sx]+/g,""));regex._x={source:pattern,captureNames:hasNamedCapture?captureNames:null};return regex};XRegExp.addPlugin=function(name,o){plugins[name]=o};RegExp.prototype.exec=function(str){var match=real.exec.call(this,str),name,i,r2;if(match){if(brokenExecUndef&&match.length>1){r2=new RegExp("^"+this.source+"$(?!\\s)",this.getNativeFlags());real.replace.call(match[0],r2,function(){for(i=1;i(match.index+match[0].length)){this.lastIndex--}}return match}})()}RegExp.prototype.getNativeFlags=function(){return(this.global?"g":"")+(this.ignoreCase?"i":"")+(this.multiline?"m":"")+(this.extended?"x":"")+(this.sticky?"y":"")};RegExp.prototype.addFlags=function(flags){var regex=new XRegExp(this.source,(flags||"")+this.getNativeFlags());if(this._x){regex._x={source:this._x.source,captureNames:this._x.captureNames?this._x.captureNames.slice(0):null}}return regex};RegExp.prototype.call=function(context,str){return this.exec(str)};RegExp.prototype.apply=function(context,args){return this.exec(args[0])};XRegExp.cache=function(pattern,flags){var key="/"+pattern+"/"+(flags||"");return XRegExp.cache[key]||(XRegExp.cache[key]=new XRegExp(pattern,flags))};XRegExp.escape=function(str){return str.replace(/[-[\]{}()*+?.\\^$|,#\s]/g,"\\$&")};XRegExp.matchRecursive=function(str,left,right,flags,options){var options=options||{},escapeChar=options.escapeChar,vN=options.valueNames,flags=flags||"",global=flags.indexOf("g")>-1,ignoreCase=flags.indexOf("i")>-1,multiline=flags.indexOf("m")>-1,sticky=flags.indexOf("y")>-1,flags=flags.replace(/y/g,""),left=left instanceof RegExp?(left.global?left:left.addFlags("g")):new XRegExp(left,"g"+flags),right=right instanceof RegExp?(right.global?right:right.addFlags("g")):new XRegExp(right,"g"+flags),output=[],openTokens=0,delimStart=0,delimEnd=0,lastOuterEnd=0,outerStart,innerStart,leftMatch,rightMatch,escaped,esc;if(escapeChar){if(escapeChar.length>1){throw SyntaxError("can't supply more than one escape character")}if(multiline){throw TypeError("can't supply escape character when using the multiline flag")}escaped=XRegExp.escape(escapeChar);esc=new RegExp("^(?:"+escaped+"[\\S\\s]|(?:(?!"+left.source+"|"+right.source+")[^"+escaped+"])+)+",ignoreCase?"i":"")}while(true){left.lastIndex=right.lastIndex=delimEnd+(escapeChar?(esc.exec(str.slice(delimEnd))||[""])[0].length:0);leftMatch=left.exec(str);rightMatch=right.exec(str);if(leftMatch&&rightMatch){if(leftMatch.index<=rightMatch.index){rightMatch=null}else{leftMatch=null}}if(leftMatch||rightMatch){delimStart=(leftMatch||rightMatch).index;delimEnd=(leftMatch?left:right).lastIndex}else{if(!openTokens){break}}if(sticky&&!openTokens&&delimStart>lastOuterEnd){break}if(leftMatch){if(!openTokens++){outerStart=delimStart;innerStart=delimEnd}}else{if(rightMatch&&openTokens){if(!--openTokens){if(vN){if(vN[0]&&outerStart>lastOuterEnd){output.push([vN[0],str.slice(lastOuterEnd,outerStart),lastOuterEnd,outerStart])}if(vN[1]){output.push([vN[1],str.slice(outerStart,innerStart),outerStart,innerStart])}if(vN[2]){output.push([vN[2],str.slice(innerStart,delimStart),innerStart,delimStart])}if(vN[3]){output.push([vN[3],str.slice(delimStart,delimEnd),delimStart,delimEnd])}}else{output.push(str.slice(innerStart,delimStart))}lastOuterEnd=delimEnd;if(!global){break}}}else{left.lastIndex=right.lastIndex=0;throw Error("subject data contains unbalanced delimiters")}}if(delimStart===delimEnd){delimEnd++}}if(global&&!sticky&&vN&&vN[0]&&str.length>lastOuterEnd){output.push([vN[0],str.slice(lastOuterEnd),lastOuterEnd,str.length])}left.lastIndex=right.lastIndex=0;return output}; SyntaxHighlighter.config.bloggerMode = true; SyntaxHighlighter.all(); //-->

2011/02/02

Slim3 JSON機能の説明(非公式)

(2/7更新)
(2/26更新)
(12/22更新 @Jsonはフィールド直接指定になりました)

Slim3 JSON機能のドキュメントを書き始めました。まだ非公式なものですが、ひと通り書き終わったら公式へのマージを提案する予定です。でも、公式は英語なんですよね。どうしたものか。まぁ、いきなり下手な英語で書くより、まずは日本語でちゃんと書いたほうが良いはず。

というわけで、下記ドキュメントの草案です。若干改行が変ですが、evernoteに書きなぐってexportしたものを貼っつけてるためだと思います。これにあとJSON入出力のカスタマイズ方法を書いて一段落とする予定です。(書きました!)

概要
 Slim3のJSON機能は、モデル(@org.slim3.datastore.Modelアノテーションが付加されたクラス)のJSON変換機能を提供します。JSON変換は、org.slim3.datastore.ModelMeta<M>に定義される以下のメソッドを呼び出すことにより行われます。

モデルのJSON文字列への変換:
  • String modelToJson(Object model);
  • String modelToJson(Object model, int maxDepth);
  • String modelsToJson(Object[] models);
  • String modelsToJson(Object[] models, int maxDepth);
JSON文字列のモデルへの変換:

  • M jsonToModel(String json);
  • M jsonToModel(String json, int maxDepth);
  • M[] jsonToModels(String json);
  • M[] jsonToModels(String json, int maxDepth);
 例えばTestModelというモデルに対してJSON変換機能を使用するコードは、次のようになります。

TestModel m = new TestModel();
m.setValue(1);
String json = TestModelMeta.get().modelToJson(m);
System.out.println(json); // {"value": 1}
TestModel m2 = TestModelMeta.get().jsonToModel(json);
Assert.assertEquals(m.getValue(), m2.getValue());


JSON変換の制御
 フィールドにJSONアノテーション(@org.slim3.datastore.json.JSON)を指定することで、JSON変換の振る舞いを変更できます。以下にJSONアノテーションで指定できるパラメータを示します。

パラメータ名 デフォルト 説明
ignore boolean false このアトリビュートを無視します。JSON出力に含まれず、JSON入力時にも読み込まれません。
ignoreNull boolean true アトリビュートがnullの場合、何も出力しません。falseの場合は、"null"が出力されます。
alias String 空文字列 アトリビュートのJSON文字列内での名前を指定します。
coder Class<? extends JsonCoder> Default.class JSON入出力を行うJsonCoderのクラスを指定します。ここに独自のクラスを指定することで、JSON入出力のカスタマイズを行うことができます(後述)。

 例えばプロパティを無視したり、エイリアスを設定したりする場合、以下のように記述します。

@Model
class TestModel{
  ...
  @Json(ignore=true)
  private String ignoredValue;
  @Json(alise="foo")
  private String bar;
}


対応する値型
 Slim3のJSON変換機能は、以下の値型に対応します。また、後述するカスタマイズを行えば、これ以外の型に対応したり、入出力方法を変更する事ができます。

Javaクラス
JSON表現
java.lang.String, com.google.appengine.api.datastore.Text
文字列。cipher=trueの場合、JSON内では暗号化されます。
"text":"hello"
byte[], com.google.appengine.api.datastore.ShortBlob, com.google.appengine.api.datastore.Blob
バイト列のBase64文字列。
"blob":"mMB4qZAgtBKJq0d1LBGTCA=="
boolean, java.lang.Boolean
ブール値(true or false)。
"value":true
short, java.lang.Short, int, java.lang.Integer, long, java.lang.Long
整数。
"value":100
float, java.lang.Float, double, java.lang.Double
小数。
"value":1.0
java.util.Date
整数(Date.getTime()が返す値)。
"value":10233400
java.lang.Enum
文字列(Enum.name()が返す値)。
"value":"MONDAY"
com.google.appengine.api.users.User
ネストしたJSON文字列(User.getEmail()等の値をJSONエンコード)。
"user":{"authDomain":"authDomain","email":"[email protected]"}
com.google.appengine.api.datastore.Key
文字列(KeyFactory.keyToString(Key)の実行結果)。
"key":"aglzbGltMy1nZW5yCwsSBHRlc3QY6AcM"
com.google.appengine.api.datastore.Category
文字列(Category.getCategory()の値)。
"category":"partOfSpeech"
com.google.appengine.api.datastore.Email
文字列(Email.getEmail()の値)。
"mail":"[email protected]"
com.google.appengine.api.datastore.GeoPt
ネストしたJSON文字列(GeoPt.getLatitude()及びGeoPt.getLongitude()の値をJSONエンコード)。
"geopt":{"latitude":10.0,"longitude":10.0}
com.google.appengine.api.datastore.IMHandle
ネストしたJSON文字列(IMHandle.getAddress()及びIMHandle.getProtocol()の値をJSONエンコード)。
"handle":{"address":"handle","protocol":"xmpp"}
com.google.appengine.api.datastore.Link
文字列(Link.getValue()の値)。
"link":"linkValue"
com.google.appengine.api.datastore.PhoneNumber
文字列(PhoneNumber.getNumber()の値)。
"phone":"000-000-000"
com.google.appengine.api.datastore.PostalAddress
文字列(PostalAddress.getAddress()の値)。
"address":"Tokyo, Japan"
com.google.appengine.api.datastore.Rating
整数(Rating.getRating()の値)。
"rating":100
com.google.appengine.api.blobstore.BlobKey
文字列(BlobKey.getKeyString()の値)。
"blobkey":"Q3PqkweYlb4iWpp0BVw"
org.slim3.datastore.ModelRef<M>
文字列(モデルのkeyに対してKeyFactory.keyToString(key)した結果)。
"ref":{"key":"lskfo2ijalefkwejfwlke",value:100}

 また上記サポートする型のコレクションにも対応しています。対応するコレクションクラスはjava.util.List, java.util.Set, java.util.SortedSetで、JSON文字列からモデルを作成する際は、それぞれjava.util.ArrayList、java.util.HashSet、java.util.TreeSetをnewして要素を追加したものがセットされます。


ModelRef<M>の展開
 デフォルトではJSONアノテーションのcoderパラメータにorg.slim3.datastore.json.Defaultが指定されたものとして扱われ、このクラスは、ModelRefを参照先のモデルのキーに変換します。参照先のモデルの内容を展開したい場合、org.slim3.datastore.json.Expandedを指定して下さい。このクラスは、参照先のモデルの内容を展開し、そのモデルがさらにModelRefを持っている場合も展開します。展開のネストの深さは、modelToJsonメソッドやjsonToModelメソッドの、maxDepth引数で制限できます。
 以下にコード例を示します。

@Model
class TestModel{
  ...
  @Json(coder=Expanded.class)
  private ModelRef<TestModel> ref = new ModelRef<TestModel>(TestModel.class);
}
...
TestModel m = new TestModel();
TestModelMeta.get().modelToJson(m, 3);  // 3階層まで展開


JSON入出力のカスタマイズ
 JSONアノテーションのcoderパラメータにJSON入出力を行うクラスを指定することにより、JSON変換の振る舞いを変更することができます。デフォルトではorg.slim3.datastore.json.Defaultが指定されており、slim3が対応するデータ型のJSON入出力が行われます。slim3ではもう一つ、org.slim3.datastore.json.Expandedが用意されていて、これをModelRef<M>型のフィールドに対して使用すると、ModelRef<M>が参照しているオブジェクトも展開します。
 slim3が対応していないデータ型を使う場合や入出力方法を変更したい場合は、org.slim3.datastore.json.Defaultから継承したクラスを作成し、encode/decodeメソッドをオーバーライドして下さい。
 下記にjava.awt.Pointの入出力をサポートするクラスの例を示します。

class CustomCoder extends org.slim3.datastore.json.Default{
  public void encode(JsonWriter writer, Object value){
    if(value instanceof java.awt.Point){
      java.awt.Point pt = (java.awt.Point)value;
      writer.beginObject();
      writer.writeValueProperty("x", pt.x);
      writer.writeValueProperty("y", pt.y);
      writer.endObject();
    } else{
      super.encode(writer, value);
  }
  public <T> T decode(JsonReader reader, T defaultValue, Class<T> clazz){
    if(java.awt.Point.isAssignableFrom(clazz)){
      try{
        int x = Integer.parseInt(reader.readProperty("x");
        int y = Integer.parseInt(reader.readProperty("y");
        return clazz.cast(new Point(x, y));
      } catch(NumberFormatException e){
      }
    }
    return defaultValue;
  }
}

 java.awt.PointクラスのフィールドをJSON入出力の対象にするには、上記のCustomCoderをcoderパラメータに指定します。

import java.awt.Point;

@Model
class TestModel{
  public Key getKey(){
    return key;
  }

  public void setKey(Key key){
    this.key = key;
  }

  public Point getPoint(){
    return point;
  }

  public void setPoint(Point point){
    this.point = point;
  }

  @Attribute(primariKey=true)
  private Key key;

  @Attribute(persistent=false)
  @Json(coder=CustomCoder.class)
  private Point point;

}

 上記のように指定すると、java.awt.Point型のpointフィールドのJSON入出力がおこなえるようになります。

TestModel m = new TestModel();
m.setPoint(new Point(10, 20));
String json = TestModelMeta.get().modelToJson(m); // {"point":{"x":10,"y":20}}
TestModel m2 = TestModelMeta.get().jsonToModel(json);
Assert.assertEquals(m.x, m2.x);
Assert.assertEquals(m.y, m2.y); 

0 件のコメント: