You'll need to register a Morpher (from EZMorph) to handle this case. EZMorpher includes a DateMorpher that takes a date literal and transforms it into a java.util.Date but in your case you need to transform a "bean" into a java.util.Date
Cheers,
Andres
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Could you please help.
I have the following classes:
public class TestBean {
java.util.Date value;
// +Getter&Setter for value
}
public class MyDateMorpher {
public Class morphsTo() { return java.util.Date; }
public boolean supports(Class clazz) { // Not called }
public Object morph(Object value) { // Not called }
}
I think there may be a bug in EZMorph if several morphers for the same target class are registered
MorpherRegistry.morph will call the first available morpher, in your case I think a DateMorpher is already registered but it only supports String.class
Please try by deregistering any morpher for Date before calling your code again. I'll update EZMoprh anyway.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hmm I thought it should return a DateMorpher with default date formats. In any case I can confirm there is a bug in EZMorph and it has been fixed yesterday. I'll release it soon and then update json-lib-2.2-SNAPSHOT with the fix.
Cheers,
Andres
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Well that's surprising, I'll give it a look tonight and see what's happening. There is a chance a BeanMorpher is being registered automatically but if your Morpher is already in place the code should pick it up. Out of curiosity, what's the impl of your 'supports(Class clazz)' ? it should support JSONObject at least.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I ran the following test against ezmorph-1.0.4 and it works ok, you should download a copy from ezmorph's cvs and build your own as I have not released yet. No changes to json-lib are needed.
public void testToBeanWithMultipleMorphersForTargetType() {
Calendar c = Calendar.getInstance();
c.set( Calendar.YEAR, 2007 );
c.set( Calendar.MONTH, 5 );
c.set( Calendar.DAY_OF_MONTH, 17 );
c.set( Calendar.HOUR_OF_DAY, 12 );
c.set( Calendar.MINUTE, 13 );
c.set( Calendar.SECOND, 14 );
c.set( Calendar.MILLISECOND, 150 );
Date date = c.getTime();
DateBean bean = new DateBean();
bean.setDate( date );
JSONObject jsonObject = JSONObject.fromObject( bean );
JSONUtils.getMorpherRegistry()
.registerMorpher( new MapToDateMorpher() );
Actually if you are transforming back to JSON what you got from the morphed bean then it seems to me the datemorpher was called as year is 107 and day is 0. Could you please send me your testing code? I did some changes after sending the previous message and want to find out if there is a still a bug lurking somewhere, thanks.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
public class MapToDateMorpher extends AbstractObjectMorpher {
public Class morphsTo() { return Date.class; }
public Object morph( Object value ) { System.out.println("MORPH CALLED"); }
public boolean supports( Class clazz ) { System.out.println("SUPPORTS CALLED"); }
}
public class TestBean {
Date date;
// Getter,Setter
}
I get the WARNING: Property 'day' has no write method. SKIPPED.
The methods morph and supports are NOT called.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
You did noticed that I used another version of toBean, the one that accepts JsonConfig as the second parameter. But the code you show should work, perhaps this is a regression on the previous way of calling that method. I'll look further into it.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I want to convert the birthday in
{..., "birthday":{"day":5,"month":11,"year":2007}}
to a java.util.Date object.
In Java I would do it like this:
setBirthday( new GregorianCalendar( year, month-1, day ).getTime() )
How do I have to configure json-lib,
that it converts automatically with
JSONObject.toBean(...)?
Hi Jochen,
You'll need to register a Morpher (from EZMorph) to handle this case. EZMorpher includes a DateMorpher that takes a date literal and transforms it into a java.util.Date but in your case you need to transform a "bean" into a java.util.Date
Cheers,
Andres
Could you please help.
I have the following classes:
public class TestBean {
java.util.Date value;
// +Getter&Setter for value
}
public class MyDateMorpher {
public Class morphsTo() { return java.util.Date; }
public boolean supports(Class clazz) { // Not called }
public Object morph(Object value) { // Not called }
}
main() {
String jsonString = "{\"value\":{\"day\":1,\"month\":2,\"year\":1980}}";
JSONUtils.getMorpherRegistry().registerMorpher(new MyDateMorpher());
JSONObject jsonObject = JSONObject.fromObject(jsonString);
TestBean testBean = (TestBean)JSONObject.toBean(jsonObject, TestBean.class);
}
Results in:
net.sf.json.JSONObject toBean
WARNING: Property 'day' has no write method. SKIPPED.
The Morpher isn't called.
I think there may be a bug in EZMorph if several morphers for the same target class are registered
MorpherRegistry.morph will call the first available morpher, in your case I think a DateMorpher is already registered but it only supports String.class
Please try by deregistering any morpher for Date before calling your code again. I'll update EZMoprh anyway.
The morpher I get for java.util.Date is the IdentityObjectMorpher. I can't remove this one.
Hmm I thought it should return a DateMorpher with default date formats. In any case I can confirm there is a bug in EZMorph and it has been fixed yesterday. I'll release it soon and then update json-lib-2.2-SNAPSHOT with the fix.
Cheers,
Andres
I tried it with the ezmorph from the cvs repository.
There isn't even a search for a Morpher in json-lib for my example.
Well that's surprising, I'll give it a look tonight and see what's happening. There is a chance a BeanMorpher is being registered automatically but if your Morpher is already in place the code should pick it up. Out of curiosity, what's the impl of your 'supports(Class clazz)' ? it should support JSONObject at least.
I ran the following test against ezmorph-1.0.4 and it works ok, you should download a copy from ezmorph's cvs and build your own as I have not released yet. No changes to json-lib are needed.
public void testToBeanWithMultipleMorphersForTargetType() {
Calendar c = Calendar.getInstance();
c.set( Calendar.YEAR, 2007 );
c.set( Calendar.MONTH, 5 );
c.set( Calendar.DAY_OF_MONTH, 17 );
c.set( Calendar.HOUR_OF_DAY, 12 );
c.set( Calendar.MINUTE, 13 );
c.set( Calendar.SECOND, 14 );
c.set( Calendar.MILLISECOND, 150 );
Date date = c.getTime();
DateBean bean = new DateBean();
bean.setDate( date );
JSONObject jsonObject = JSONObject.fromObject( bean );
JSONUtils.getMorpherRegistry()
.registerMorpher( new MapToDateMorpher() );
JsonConfig jsonConfig = new JsonConfig();
jsonConfig.setRootClass( DateBean.class );
DateBean actual = (DateBean) JSONObject.toBean( jsonObject, jsonConfig );
Calendar d = Calendar.getInstance();
d.setTime( actual.getDate() );
assertEquals( c.get( Calendar.YEAR ), d.get( Calendar.YEAR ) );
assertEquals( c.get( Calendar.MONTH ), d.get( Calendar.MONTH ) );
assertEquals( c.get( Calendar.DATE ), d.get( Calendar.DATE ) );
assertEquals( c.get( Calendar.HOUR_OF_DAY ), d.get( Calendar.HOUR_OF_DAY ) );
assertEquals( c.get( Calendar.MINUTE ), d.get( Calendar.MINUTE ) );
assertEquals( c.get( Calendar.SECOND ), d.get( Calendar.SECOND ) );
assertEquals( c.get( Calendar.MILLISECOND ), d.get( Calendar.MILLISECOND ) );
}
public class MapToDateMorpher extends AbstractObjectMorpher {
public Object morph( Object value ) {
if( value == null || !(value instanceof Map) ){
return null;
}
Map map = (Map) value;
Calendar c = Calendar.getInstance();
c.set( Calendar.YEAR, getValue( map, "year" ) );
c.set( Calendar.MONTH, getValue( map, "month" ) );
c.set( Calendar.DATE, getValue( map, "day" ) );
c.set( Calendar.HOUR_OF_DAY, getValue( map, "hour" ) );
c.set( Calendar.MINUTE, getValue( map, "minutes" ) );
c.set( Calendar.SECOND, getValue( map, "seconds" ) );
c.set( Calendar.MILLISECOND, getValue( map, "milliseconds" ) );
return c.getTime();
}
public Class morphsTo() {
return Date.class;
}
public boolean supports( Class clazz ) {
return clazz != null && Map.class.isAssignableFrom( clazz );
}
private int getValue( Map map, String key ) {
Object value = map.get( key );
if( value == null || !(value instanceof Number) ){
return 0;
}
Number n = (Number) value;
return n.intValue();
}
}
I testet it with ezmorph-1.0.4. The Morpher isn't called.
Look at the 'day' in the JSON string: {"month":5,"day":0,"year":107,...} It is 0.
Actually if you are transforming back to JSON what you got from the morphed bean then it seems to me the datemorpher was called as year is 107 and day is 0. Could you please send me your testing code? I did some changes after sending the previous message and want to find out if there is a still a bug lurking somewhere, thanks.
I'm doing this:
main() {
String jsonString = "{\"date\":{\"day\":15,\"month\":5,\"year\":1977}}";
JSONObject json = JSONObject.fromObject(jsonString);
JSONUtils.getMorpherRegistry().registerMorpher( new MapToDateMorpher() );
TestBean actual = (TestBean) JSONObject.toBean( json, TestBean.class );
}
public class MapToDateMorpher extends AbstractObjectMorpher {
public Class morphsTo() { return Date.class; }
public Object morph( Object value ) { System.out.println("MORPH CALLED"); }
public boolean supports( Class clazz ) { System.out.println("SUPPORTS CALLED"); }
}
public class TestBean {
Date date;
// Getter,Setter
}
I get the WARNING: Property 'day' has no write method. SKIPPED.
The methods morph and supports are NOT called.
You did noticed that I used another version of toBean, the one that accepts JsonConfig as the second parameter. But the code you show should work, perhaps this is a regression on the previous way of calling that method. I'll look further into it.