1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package net.sf.json;
17
18 import java.beans.PropertyDescriptor;
19 import java.io.IOException;
20 import java.io.Writer;
21 import java.lang.reflect.Array;
22 import java.lang.reflect.Field;
23 import java.lang.reflect.Modifier;
24 import java.util.Collection;
25 import java.util.Collections;
26 import java.util.HashMap;
27 import java.util.Iterator;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.Set;
31
32 import net.sf.ezmorph.Morpher;
33 import net.sf.ezmorph.array.ObjectArrayMorpher;
34 import net.sf.ezmorph.bean.BeanMorpher;
35 import net.sf.ezmorph.object.IdentityObjectMorpher;
36 import net.sf.json.processors.JsonBeanProcessor;
37 import net.sf.json.processors.JsonValueProcessor;
38 import net.sf.json.processors.JsonVerifier;
39 import net.sf.json.processors.PropertyNameProcessor;
40 import net.sf.json.regexp.RegexpUtils;
41 import net.sf.json.util.CycleDetectionStrategy;
42 import net.sf.json.util.JSONTokener;
43 import net.sf.json.util.JSONUtils;
44 import net.sf.json.util.PropertyFilter;
45 import net.sf.json.util.PropertySetStrategy;
46
47 import org.apache.commons.beanutils.DynaBean;
48 import org.apache.commons.beanutils.DynaProperty;
49 import org.apache.commons.beanutils.PropertyUtils;
50 import org.apache.commons.collections.map.ListOrderedMap;
51 import org.apache.commons.lang.StringUtils;
52 import org.apache.commons.logging.Log;
53 import org.apache.commons.logging.LogFactory;
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110 public final class JSONObject extends AbstractJSON implements JSON, Map, Comparable {
111
112 private static final Log log = LogFactory.getLog( JSONObject.class );
113
114
115
116
117
118
119
120
121
122
123
124 public static JSONObject fromObject( Object object ) {
125 return fromObject( object, new JsonConfig() );
126 }
127
128
129
130
131
132
133
134
135
136
137 public static JSONObject fromObject( Object object, JsonConfig jsonConfig ) {
138 if( object == null || JSONUtils.isNull( object ) ){
139 return new JSONObject( true );
140 }else if( object instanceof JSONObject ){
141 return _fromJSONObject( (JSONObject) object, jsonConfig );
142 }else if( object instanceof DynaBean ){
143 return _fromDynaBean( (DynaBean) object, jsonConfig );
144 }else if( object instanceof JSONTokener ){
145 return _fromJSONTokener( (JSONTokener) object, jsonConfig );
146 }else if( object instanceof JSONString ){
147 return _fromJSONString( (JSONString) object, jsonConfig );
148 }else if( object instanceof Map ){
149 return _fromMap( (Map) object, jsonConfig );
150 }else if( object instanceof String ){
151 return _fromString( (String) object, jsonConfig );
152 }else if( JSONUtils.isNumber( object ) || JSONUtils.isBoolean( object )
153 || JSONUtils.isString( object ) ){
154 return new JSONObject();
155 }else if( JSONUtils.isArray( object ) ){
156 throw new JSONException( "'object' is an array. Use JSONArray instead" );
157 }else{
158 return _fromBean( object, jsonConfig );
159 }
160 }
161
162
163
164
165 public static Object toBean( JSONObject jsonObject ) {
166 if( jsonObject == null || jsonObject.isNullObject() ){
167 return null;
168 }
169
170 DynaBean dynaBean = null;
171
172 JsonConfig jsonConfig = new JsonConfig();
173 Map props = JSONUtils.getProperties( jsonObject );
174 dynaBean = JSONUtils.newDynaBean( jsonObject, jsonConfig );
175 for( Iterator entries = jsonObject.names( jsonConfig )
176 .iterator(); entries.hasNext(); ){
177 String name = (String) entries.next();
178 String key = JSONUtils.convertToJavaIdentifier( name, jsonConfig );
179 Class type = (Class) props.get( name );
180 Object value = jsonObject.get( name );
181 try{
182 if( !JSONUtils.isNull( value ) ){
183 if( value instanceof JSONArray ){
184 dynaBean.set( key, JSONArray.toCollection( (JSONArray) value ) );
185 }else if( String.class.isAssignableFrom( type )
186 || Boolean.class.isAssignableFrom( type ) || JSONUtils.isNumber( type )
187 || Character.class.isAssignableFrom( type )
188 || JSONFunction.class.isAssignableFrom( type ) ){
189 dynaBean.set( key, value );
190 }else{
191 dynaBean.set( key, toBean( (JSONObject) value ) );
192 }
193 }else{
194 if( type.isPrimitive() ){
195
196 log.warn( "Tried to assign null value to " + key + ":" + type.getName() );
197 dynaBean.set( key, JSONUtils.getMorpherRegistry()
198 .morph( type, null ) );
199 }else{
200 dynaBean.set( key, null );
201 }
202 }
203 }catch( JSONException jsone ){
204 throw jsone;
205 }catch( Exception e ){
206 throw new JSONException( "Error while setting property=" + name + " type" + type, e );
207 }
208 }
209
210 return dynaBean;
211 }
212
213
214
215
216 public static Object toBean( JSONObject jsonObject, Class beanClass ) {
217 JsonConfig jsonConfig = new JsonConfig();
218 jsonConfig.setRootClass( beanClass );
219 return toBean( jsonObject, jsonConfig );
220 }
221
222
223
224
225
226
227
228
229
230
231
232
233
234 public static Object toBean( JSONObject jsonObject, Class beanClass, Map classMap ) {
235 JsonConfig jsonConfig = new JsonConfig();
236 jsonConfig.setRootClass( beanClass );
237 jsonConfig.setClassMap( classMap );
238 return toBean( jsonObject, jsonConfig );
239 }
240
241
242
243
244 public static Object toBean( JSONObject jsonObject, JsonConfig jsonConfig ) {
245 if( jsonObject == null || jsonObject.isNullObject() ){
246 return null;
247 }
248
249 Class beanClass = jsonConfig.getRootClass();
250 Map classMap = jsonConfig.getClassMap();
251
252 if( beanClass == null ){
253 return toBean( jsonObject );
254 }
255 if( classMap == null ){
256 classMap = Collections.EMPTY_MAP;
257 }
258
259 Object bean = null;
260 try{
261 if( beanClass.isInterface() ){
262 if( !Map.class.isAssignableFrom( beanClass ) ){
263 throw new JSONException( "beanClass is an interface. " + beanClass );
264 }else{
265 bean = new HashMap();
266 }
267 }else{
268 bean = jsonConfig.getNewBeanInstanceStrategy()
269 .newInstance( beanClass, jsonObject );
270 }
271 }catch( JSONException jsone ){
272 throw jsone;
273 }catch( Exception e ){
274 throw new JSONException( e );
275 }
276
277 Map props = JSONUtils.getProperties( jsonObject );
278 PropertyFilter javaPropertyFilter = jsonConfig.getJavaPropertyFilter();
279 for( Iterator entries = jsonObject.names( jsonConfig )
280 .iterator(); entries.hasNext(); ){
281 String name = (String) entries.next();
282 Class type = (Class) props.get( name );
283 Object value = jsonObject.get( name );
284 if( javaPropertyFilter != null && javaPropertyFilter.apply( bean, name, value ) ){
285 continue;
286 }
287 String key = Map.class.isAssignableFrom( beanClass )
288 && jsonConfig.isSkipJavaIdentifierTransformationInMapKeys() ? name
289 : JSONUtils.convertToJavaIdentifier( name, jsonConfig );
290 PropertyNameProcessor propertyNameProcessor = jsonConfig.findJavaPropertyNameProcessor( beanClass );
291 if( propertyNameProcessor != null ){
292 key = propertyNameProcessor.processPropertyName( beanClass, key );
293 }
294 try{
295 if( Map.class.isAssignableFrom( beanClass ) ){
296
297 if( JSONUtils.isNull( value ) ){
298 setProperty( bean, key, value, jsonConfig );
299 }else if( value instanceof JSONArray ){
300 setProperty( bean, key, convertPropertyValueToCollection( key, value, jsonConfig, name,
301 classMap, List.class ), jsonConfig );
302 }else if( String.class.isAssignableFrom( type ) || JSONUtils.isBoolean( type )
303 || JSONUtils.isNumber( type ) || JSONUtils.isString( type )
304 || JSONFunction.class.isAssignableFrom( type ) ){
305 if( jsonConfig.isHandleJettisonEmptyElement() && "".equals( value ) ){
306 setProperty( bean, key, null, jsonConfig );
307 }else{
308 setProperty( bean, key, value, jsonConfig );
309 }
310 }else{
311 Class targetClass = findTargetClass( key, classMap );
312 targetClass = targetClass == null ? findTargetClass( name, classMap )
313 : targetClass;
314 JsonConfig jsc = jsonConfig.copy();
315 jsc.setRootClass( targetClass );
316 jsc.setClassMap( classMap );
317 if( targetClass != null ){
318 setProperty( bean, key, toBean( (JSONObject) value, jsc ), jsonConfig );
319 }else{
320 setProperty( bean, key, toBean( (JSONObject) value ), jsonConfig );
321 }
322 }
323 }else{
324 PropertyDescriptor pd = PropertyUtils.getPropertyDescriptor( bean, key );
325 if( pd != null && pd.getWriteMethod() == null ){
326 log.info( "Property '" + key + "' of "+ bean.getClass()+" has no write method. SKIPPED." );
327 continue;
328 }
329
330 if( pd != null ){
331 Class targetType = pd.getPropertyType();
332 if( !JSONUtils.isNull( value ) ){
333 if( value instanceof JSONArray ){
334 if( List.class.isAssignableFrom( pd.getPropertyType() ) ){
335 setProperty( bean, key, convertPropertyValueToCollection( key, value,
336 jsonConfig, name, classMap, pd.getPropertyType() ), jsonConfig );
337 }else if( Set.class.isAssignableFrom( pd.getPropertyType() ) ){
338 setProperty( bean, key, convertPropertyValueToCollection( key, value,
339 jsonConfig, name, classMap, pd.getPropertyType() ), jsonConfig );
340 }else{
341 setProperty( bean, key, convertPropertyValueToArray( key, value,
342 targetType, jsonConfig, classMap ), jsonConfig );
343 }
344 }else if( String.class.isAssignableFrom( type ) || JSONUtils.isBoolean( type )
345 || JSONUtils.isNumber( type ) || JSONUtils.isString( type )
346 || JSONFunction.class.isAssignableFrom( type ) ){
347 if( pd != null ){
348 if( jsonConfig.isHandleJettisonEmptyElement() && "".equals( value ) ){
349 setProperty( bean, key, null, jsonConfig );
350 }else if( !targetType.isInstance( value ) ){
351 setProperty( bean, key, morphPropertyValue( key, value, type,
352 targetType ), jsonConfig );
353 }else{
354 setProperty( bean, key, value, jsonConfig );
355 }
356 }else if( beanClass == null || bean instanceof Map ){
357 setProperty( bean, key, value, jsonConfig );
358 }else{
359 log.warn( "Tried to assign property " + key + ":" + type.getName()
360 + " to bean of class " + bean.getClass()
361 .getName() );
362 }
363 }else{
364 if( jsonConfig.isHandleJettisonSingleElementArray() ){
365 JSONArray array = new JSONArray().element( value, jsonConfig );
366 Class newTargetClass = findTargetClass( key, classMap );
367 newTargetClass = newTargetClass == null ? findTargetClass( name,
368 classMap ) : newTargetClass;
369 JsonConfig jsc = jsonConfig.copy();
370 jsc.setRootClass( newTargetClass );
371 jsc.setClassMap( classMap );
372 if( targetType.isArray() ){
373 setProperty( bean, key, JSONArray.toArray( array, jsc ), jsonConfig );
374 }else if( JSONArray.class.isAssignableFrom( targetType ) ){
375 setProperty( bean, key, array, jsonConfig );
376 }else if( List.class.isAssignableFrom( targetType )
377 || Set.class.isAssignableFrom( targetType ) ){
378 jsc.setCollectionType( targetType );
379 setProperty( bean, key, JSONArray.toCollection( array, jsc ),
380 jsonConfig );
381 }else{
382 setProperty( bean, key, toBean( (JSONObject) value, jsc ), jsonConfig );
383 }
384 }else{
385 if( targetType == Object.class || targetType.isInterface() ) {
386 Class targetTypeCopy = targetType;
387 targetType = findTargetClass( key, classMap );
388 targetType = targetType == null ? findTargetClass( name, classMap )
389 : targetType;
390 targetType = targetType == null && targetTypeCopy.isInterface() ? targetTypeCopy
391 : targetType;
392 }
393 JsonConfig jsc = jsonConfig.copy();
394 jsc.setRootClass( targetType );
395 jsc.setClassMap( classMap );
396 setProperty( bean, key, toBean( (JSONObject) value, jsc ), jsonConfig );
397 }
398 }
399 }else{
400 if( type.isPrimitive() ){
401
402 log.warn( "Tried to assign null value to " + key + ":" + type.getName() );
403 setProperty( bean, key, JSONUtils.getMorpherRegistry()
404 .morph( type, null ), jsonConfig );
405 }else{
406 setProperty( bean, key, null, jsonConfig );
407 }
408 }
409 }else{
410
411 if( !JSONUtils.isNull( value ) ){
412 if( value instanceof JSONArray ){
413 setProperty( bean, key, convertPropertyValueToCollection( key, value,
414 jsonConfig, name, classMap, List.class ), jsonConfig );
415 }else if( String.class.isAssignableFrom( type ) || JSONUtils.isBoolean( type )
416 || JSONUtils.isNumber( type ) || JSONUtils.isString( type )
417 || JSONFunction.class.isAssignableFrom( type ) ){
418 if( beanClass == null || bean instanceof Map || jsonConfig.getPropertySetStrategy() != null ||
419 !jsonConfig.isIgnorePublicFields() ){
420 setProperty( bean, key, value, jsonConfig );
421 }else{
422 log.warn( "Tried to assign property " + key + ":" + type.getName()
423 + " to bean of class " + bean.getClass()
424 .getName() );
425 }
426 }else{
427 if( jsonConfig.isHandleJettisonSingleElementArray() ){
428 Class newTargetClass = findTargetClass( key, classMap );
429 newTargetClass = newTargetClass == null ? findTargetClass( name,
430 classMap ) : newTargetClass;
431 JsonConfig jsc = jsonConfig.copy();
432 jsc.setRootClass( newTargetClass );
433 jsc.setClassMap( classMap );
434 setProperty( bean, key, toBean( (JSONObject) value, jsc ), jsonConfig );
435 }else{
436 setProperty( bean, key, value, jsonConfig );
437 }
438 }
439 }else{
440 if( type.isPrimitive() ){
441
442 log.warn( "Tried to assign null value to " + key + ":" + type.getName() );
443 setProperty( bean, key, JSONUtils.getMorpherRegistry()
444 .morph( type, null ), jsonConfig );
445 }else{
446 setProperty( bean, key, null, jsonConfig );
447 }
448 }
449 }
450 }
451 }catch( JSONException jsone ){
452 throw jsone;
453 }catch( Exception e ){
454 throw new JSONException( "Error while setting property=" + name + " type " + type, e );
455 }
456 }
457
458 return bean;
459 }
460
461
462
463
464 public static Object toBean( JSONObject jsonObject, Object root, JsonConfig jsonConfig ) {
465 if( jsonObject == null || jsonObject.isNullObject() || root == null ){
466 return root;
467 }
468
469 Class rootClass = root.getClass();
470 if( rootClass.isInterface() ){
471 throw new JSONException( "Root bean is an interface. " + rootClass );
472 }
473
474 Map classMap = jsonConfig.getClassMap();
475 if( classMap == null ){
476 classMap = Collections.EMPTY_MAP;
477 }
478
479 Map props = JSONUtils.getProperties( jsonObject );
480 PropertyFilter javaPropertyFilter = jsonConfig.getJavaPropertyFilter();
481 for( Iterator entries = jsonObject.names( jsonConfig )
482 .iterator(); entries.hasNext(); ){
483 String name = (String) entries.next();
484 Class type = (Class) props.get( name );
485 Object value = jsonObject.get( name );
486 if( javaPropertyFilter != null && javaPropertyFilter.apply( root, name, value ) ){
487 continue;
488 }
489 String key = JSONUtils.convertToJavaIdentifier( name, jsonConfig );
490 try{
491 PropertyDescriptor pd = PropertyUtils.getPropertyDescriptor( root, key );
492 if( pd != null && pd.getWriteMethod() == null ){
493 log.info( "Property '" + key + "' of "+ root.getClass()+" has no write method. SKIPPED." );
494 continue;
495 }
496
497 if( !JSONUtils.isNull( value ) ){
498 if( value instanceof JSONArray ){
499 if( pd == null || List.class.isAssignableFrom( pd.getPropertyType() ) ){
500 Class targetClass = findTargetClass( key, classMap );
501 targetClass = targetClass == null ? findTargetClass( name, classMap )
502 : targetClass;
503 Object newRoot = jsonConfig.getNewBeanInstanceStrategy()
504 .newInstance( targetClass, null );
505 List list = JSONArray.toList( (JSONArray) value, newRoot, jsonConfig );
506 setProperty( root, key, list, jsonConfig );
507 }else{
508 Class innerType = JSONUtils.getInnerComponentType( pd.getPropertyType() );
509 Class targetInnerType = findTargetClass( key, classMap );
510 if( innerType.equals( Object.class ) && targetInnerType != null
511 && !targetInnerType.equals( Object.class ) ){
512 innerType = targetInnerType;
513 }
514 Object newRoot = jsonConfig.getNewBeanInstanceStrategy()
515 .newInstance( innerType, null );
516 Object array = JSONArray.toArray( (JSONArray) value, newRoot, jsonConfig );
517 if( innerType.isPrimitive() || JSONUtils.isNumber( innerType )
518 || Boolean.class.isAssignableFrom( innerType )
519 || JSONUtils.isString( innerType ) ){
520 array = JSONUtils.getMorpherRegistry()
521 .morph( Array.newInstance( innerType, 0 )
522 .getClass(), array );
523 }else if( !array.getClass()
524 .equals( pd.getPropertyType() ) ){
525 if( !pd.getPropertyType()
526 .equals( Object.class ) ){
527 Morpher morpher = JSONUtils.getMorpherRegistry()
528 .getMorpherFor( Array.newInstance( innerType, 0 )
529 .getClass() );
530 if( IdentityObjectMorpher.getInstance()
531 .equals( morpher ) ){
532 ObjectArrayMorpher beanMorpher = new ObjectArrayMorpher(
533 new BeanMorpher( innerType, JSONUtils.getMorpherRegistry() ) );
534 JSONUtils.getMorpherRegistry()
535 .registerMorpher( beanMorpher );
536 }
537 array = JSONUtils.getMorpherRegistry()
538 .morph( Array.newInstance( innerType, 0 )
539 .getClass(), array );
540 }
541 }
542 setProperty( root, key, array, jsonConfig );
543 }
544 }else if( String.class.isAssignableFrom( type ) || JSONUtils.isBoolean( type )
545 || JSONUtils.isNumber( type ) || JSONUtils.isString( type )
546 || JSONFunction.class.isAssignableFrom( type ) ){
547 if( pd != null ){
548 if( jsonConfig.isHandleJettisonEmptyElement() && "".equals( value ) ){
549 setProperty( root, key, null, jsonConfig );
550 }else if( !pd.getPropertyType()
551 .isInstance( value ) ){
552 Morpher morpher = JSONUtils.getMorpherRegistry()
553 .getMorpherFor( pd.getPropertyType() );
554 if( IdentityObjectMorpher.getInstance()
555 .equals( morpher ) ){
556 log.warn( "Can't transform property '" + key + "' from "
557 + type.getName() + " into " + pd.getPropertyType()
558 .getName() + ". Will register a default BeanMorpher" );
559 JSONUtils.getMorpherRegistry()
560 .registerMorpher(
561 new BeanMorpher( pd.getPropertyType(),
562 JSONUtils.getMorpherRegistry() ) );
563 }
564 setProperty( root, key, JSONUtils.getMorpherRegistry()
565 .morph( pd.getPropertyType(), value ), jsonConfig );
566 }else{
567 setProperty( root, key, value, jsonConfig );
568 }
569 }else if( root instanceof Map ){
570 setProperty( root, key, value, jsonConfig );
571 }else{
572 log.warn( "Tried to assign property " + key + ":" + type.getName()
573 + " to bean of class " + root.getClass()
574 .getName() );
575 }
576 }else{
577 if( pd != null ){
578 Class targetClass = pd.getPropertyType();
579 if( jsonConfig.isHandleJettisonSingleElementArray() ){
580 JSONArray array = new JSONArray().element( value, jsonConfig );
581 Class newTargetClass = findTargetClass( key, classMap );
582 newTargetClass = newTargetClass == null ? findTargetClass( name, classMap )
583 : newTargetClass;
584 Object newRoot = jsonConfig.getNewBeanInstanceStrategy()
585 .newInstance( newTargetClass, null );
586 if( targetClass.isArray() ){
587 setProperty( root, key, JSONArray.toArray( array, newRoot, jsonConfig ),
588 jsonConfig );
589 }else if( Collection.class.isAssignableFrom( targetClass ) ){
590 setProperty( root, key, JSONArray.toList( array, newRoot, jsonConfig ),
591 jsonConfig );
592 }else if( JSONArray.class.isAssignableFrom( targetClass ) ){
593 setProperty( root, key, array, jsonConfig );
594 }else{
595 setProperty( root, key,
596 toBean( (JSONObject) value, newRoot, jsonConfig ), jsonConfig );
597 }
598 }else{
599 if( targetClass == Object.class ){
600 targetClass = findTargetClass( key, classMap );
601 targetClass = targetClass == null ? findTargetClass( name, classMap )
602 : targetClass;
603 }
604 Object newRoot = jsonConfig.getNewBeanInstanceStrategy()
605 .newInstance( targetClass, null );
606 setProperty( root, key, toBean( (JSONObject) value, newRoot, jsonConfig ),
607 jsonConfig );
608 }
609 }else if( root instanceof Map ){
610 Class targetClass = findTargetClass( key, classMap );
611 targetClass = targetClass == null ? findTargetClass( name, classMap )
612 : targetClass;
613 Object newRoot = jsonConfig.getNewBeanInstanceStrategy()
614 .newInstance( targetClass, null );
615 setProperty( root, key, toBean( (JSONObject) value, newRoot, jsonConfig ),
616 jsonConfig );
617 }else{
618 log.warn( "Tried to assign property " + key + ":" + type.getName()
619 + " to bean of class " + rootClass.getName() );
620 }
621 }
622 }else{
623 if( type.isPrimitive() ){
624
625 log.warn( "Tried to assign null value to " + key + ":" + type.getName() );
626 setProperty( root, key, JSONUtils.getMorpherRegistry()
627 .morph( type, null ), jsonConfig );
628 }else{
629 setProperty( root, key, null, jsonConfig );
630 }
631 }
632 }catch( JSONException jsone ){
633 throw jsone;
634 }catch( Exception e ){
635 throw new JSONException( "Error while setting property=" + name + " type " + type, e );
636 }
637 }
638
639 return root;
640 }
641
642
643
644
645
646
647
648
649
650 private static JSONObject _fromBean( Object bean, JsonConfig jsonConfig ) {
651 if( !addInstance( bean ) ){
652 try{
653 return jsonConfig.getCycleDetectionStrategy()
654 .handleRepeatedReferenceAsObject( bean );
655 }catch( JSONException jsone ){
656 removeInstance( bean );
657 fireErrorEvent( jsone, jsonConfig );
658 throw jsone;
659 }catch( RuntimeException e ){
660 removeInstance( bean );
661 JSONException jsone = new JSONException( e );
662 fireErrorEvent( jsone, jsonConfig );
663 throw jsone;
664 }
665 }
666 fireObjectStartEvent( jsonConfig );
667
668 JsonBeanProcessor processor = jsonConfig.findJsonBeanProcessor( bean.getClass() );
669 if( processor != null ){
670 JSONObject json = null;
671 try{
672 json = processor.processBean( bean, jsonConfig );
673 if( json == null ){
674 json = (JSONObject) jsonConfig.findDefaultValueProcessor( bean.getClass() )
675 .getDefaultValue( bean.getClass() );
676 if( json == null ){
677 json = new JSONObject( true );
678 }
679 }
680 removeInstance( bean );
681 fireObjectEndEvent( jsonConfig );
682 }catch( JSONException jsone ){
683 removeInstance( bean );
684 fireErrorEvent( jsone, jsonConfig );
685 throw jsone;
686 }catch( RuntimeException e ){
687 removeInstance( bean );
688 JSONException jsone = new JSONException( e );
689 fireErrorEvent( jsone, jsonConfig );
690 throw jsone;
691 }
692 return json;
693 }
694
695 Class beanClass = bean.getClass();
696 PropertyNameProcessor propertyNameProcessor = jsonConfig.findJsonPropertyNameProcessor( beanClass );
697 Collection exclusions = jsonConfig.getMergedExcludes( beanClass );
698 JSONObject jsonObject = new JSONObject();
699 try{
700 PropertyDescriptor[] pds = PropertyUtils.getPropertyDescriptors( bean );
701 PropertyFilter jsonPropertyFilter = jsonConfig.getJsonPropertyFilter();
702 for( int i = 0; i < pds.length; i++ ){
703 boolean bypass = false;
704 String key = pds[i].getName();
705 if( exclusions.contains( key ) ){
706 continue;
707 }
708
709 if( jsonConfig.isIgnoreTransientFields() && isTransientField( key, beanClass ) ){
710 continue;
711 }
712
713 Class type = pds[i].getPropertyType();
714 try { pds[i].getReadMethod(); }
715 catch( Exception e ) {
716
717 String warning = "Property '" + key + "' of "+ beanClass+" has no read method. SKIPPED";
718 fireWarnEvent( warning, jsonConfig );
719 log.info( warning );
720 continue;
721 }
722 if( pds[i].getReadMethod() != null ){
723 Object value = PropertyUtils.getProperty( bean, key );
724 if( jsonPropertyFilter != null && jsonPropertyFilter.apply( bean, key, value ) ){
725 continue;
726 }
727 JsonValueProcessor jsonValueProcessor = jsonConfig.findJsonValueProcessor(
728 beanClass, type, key );
729 if( jsonValueProcessor != null ){
730 value = jsonValueProcessor.processObjectValue( key, value, jsonConfig );
731 bypass = true;
732 if( !JsonVerifier.isValidJsonValue( value ) ){
733 throw new JSONException( "Value is not a valid JSON value. " + value );
734 }
735 }
736 if( propertyNameProcessor != null ){
737 key = propertyNameProcessor.processPropertyName( beanClass, key );
738 }
739 setValue( jsonObject, key, value, type, jsonConfig, bypass );
740 }else{
741 String warning = "Property '" + key + "' of "+ beanClass+" has no read method. SKIPPED";
742 fireWarnEvent( warning, jsonConfig );
743 log.info( warning );
744 }
745 }
746
747
748 try {
749 if( !jsonConfig.isIgnorePublicFields() ) {
750 Field[] fields = beanClass.getFields();
751 for( int i = 0; i < fields.length; i++ ) {
752 boolean bypass = false;
753 Field field = fields[i];
754 String key = field.getName();
755 if( exclusions.contains( key ) ) {
756 continue;
757 }
758
759 if( jsonConfig.isIgnoreTransientFields() && isTransientField( field ) ) {
760 continue;
761 }
762
763 Class type = field.getType();
764 Object value = field.get( bean );
765 if( jsonPropertyFilter != null && jsonPropertyFilter.apply( bean, key, value ) ) {
766 continue;
767 }
768 JsonValueProcessor jsonValueProcessor = jsonConfig.findJsonValueProcessor( beanClass, type, key );
769 if( jsonValueProcessor != null ) {
770 value = jsonValueProcessor.processObjectValue( key, value, jsonConfig );
771 bypass = true;
772 if( !JsonVerifier.isValidJsonValue( value ) ) {
773 throw new JSONException( "Value is not a valid JSON value. " + value );
774 }
775 }
776 if( propertyNameProcessor != null ) {
777 key = propertyNameProcessor.processPropertyName( beanClass, key );
778 }
779 setValue( jsonObject, key, value, type, jsonConfig, bypass );
780 }
781 }
782 }
783 catch( Exception e ){
784 log.trace( "Couldn't read public fields.", e );
785 }
786 }catch( JSONException jsone ){
787 removeInstance( bean );
788 fireErrorEvent( jsone, jsonConfig );
789 throw jsone;
790 }catch( Exception e ){
791 removeInstance( bean );
792 JSONException jsone = new JSONException( e );
793 fireErrorEvent( jsone, jsonConfig );
794 throw jsone;
795 }
796
797 removeInstance( bean );
798 fireObjectEndEvent( jsonConfig );
799 return jsonObject;
800 }
801
802 private static JSONObject _fromDynaBean( DynaBean bean, JsonConfig jsonConfig ) {
803 if( bean == null ){
804 fireObjectStartEvent( jsonConfig );
805 fireObjectEndEvent( jsonConfig );
806 return new JSONObject( true );
807 }
808
809 if( !addInstance( bean ) ){
810 try{
811 return jsonConfig.getCycleDetectionStrategy()
812 .handleRepeatedReferenceAsObject( bean );
813 }catch( JSONException jsone ){
814 removeInstance( bean );
815 fireErrorEvent( jsone, jsonConfig );
816 throw jsone;
817 }catch( RuntimeException e ){
818 removeInstance( bean );
819 JSONException jsone = new JSONException( e );
820 fireErrorEvent( jsone, jsonConfig );
821 throw jsone;
822 }
823 }
824 fireObjectStartEvent( jsonConfig );
825
826 JSONObject jsonObject = new JSONObject();
827 try{
828 DynaProperty[] props = bean.getDynaClass()
829 .getDynaProperties();
830 Collection exclusions = jsonConfig.getMergedExcludes();
831 PropertyFilter jsonPropertyFilter = jsonConfig.getJsonPropertyFilter();
832 for( int i = 0; i < props.length; i++ ){
833 boolean bypass = false;
834 DynaProperty dynaProperty = props[i];
835 String key = dynaProperty.getName();
836 if( exclusions.contains( key ) ){
837 continue;
838 }
839 Class type = dynaProperty.getType();
840 Object value = bean.get( dynaProperty.getName() );
841 if( jsonPropertyFilter != null && jsonPropertyFilter.apply( bean, key, value ) ){
842 continue;
843 }
844 JsonValueProcessor jsonValueProcessor = jsonConfig.findJsonValueProcessor( type, key );
845 if( jsonValueProcessor != null ){
846 value = jsonValueProcessor.processObjectValue( key, value, jsonConfig );
847 bypass = true;
848 if( !JsonVerifier.isValidJsonValue( value ) ){
849 throw new JSONException( "Value is not a valid JSON value. " + value );
850 }
851 }
852 setValue( jsonObject, key, value, type, jsonConfig, bypass );
853 }
854 }catch( JSONException jsone ){
855 removeInstance( bean );
856 fireErrorEvent( jsone, jsonConfig );
857 throw jsone;
858 }catch( RuntimeException e ){
859 removeInstance( bean );
860 JSONException jsone = new JSONException( e );
861 fireErrorEvent( jsone, jsonConfig );
862 throw jsone;
863 }
864
865 removeInstance( bean );
866 fireObjectEndEvent( jsonConfig );
867 return jsonObject;
868 }
869
870 private static JSONObject _fromJSONObject( JSONObject object, JsonConfig jsonConfig ) {
871 if( object == null || object.isNullObject() ){
872 fireObjectStartEvent( jsonConfig );
873 fireObjectEndEvent( jsonConfig );
874 return new JSONObject( true );
875 }
876
877 if( !addInstance( object ) ){
878 try{
879 return jsonConfig.getCycleDetectionStrategy()
880 .handleRepeatedReferenceAsObject( object );
881 }catch( JSONException jsone ){
882 removeInstance( object );
883 fireErrorEvent( jsone, jsonConfig );
884 throw jsone;
885 }catch( RuntimeException e ){
886 removeInstance( object );
887 JSONException jsone = new JSONException( e );
888 fireErrorEvent( jsone, jsonConfig );
889 throw jsone;
890 }
891 }
892 fireObjectStartEvent( jsonConfig );
893
894 JSONArray sa = object.names(jsonConfig);
895 Collection exclusions = jsonConfig.getMergedExcludes();
896 JSONObject jsonObject = new JSONObject();
897 PropertyFilter jsonPropertyFilter = jsonConfig.getJsonPropertyFilter();
898 for( Iterator i = sa.iterator(); i.hasNext(); ){
899 Object k = i.next();
900 if( k == null ){
901 throw new JSONException("JSON keys cannot be null.");
902 }
903 if( !(k instanceof String) && !jsonConfig.isAllowNonStringKeys()) {
904 throw new ClassCastException("JSON keys must be strings.");
905 }
906 String key = String.valueOf( k );
907 if( "null".equals( key )){
908 throw new NullPointerException("JSON keys must not be null nor the 'null' string.");
909 }
910 if( exclusions.contains( key ) ){
911 continue;
912 }
913 Object value = object.opt( key );
914 if( jsonPropertyFilter != null && jsonPropertyFilter.apply( object, key, value ) ){
915 continue;
916 }
917 if( jsonObject.properties.containsKey( key ) ){
918 jsonObject.accumulate( key, value, jsonConfig );
919 firePropertySetEvent( key, value, true, jsonConfig );
920 }else{
921 jsonObject.setInternal( key, value, jsonConfig );
922 firePropertySetEvent( key, value, false, jsonConfig );
923 }
924 }
925
926 removeInstance( object );
927 fireObjectEndEvent( jsonConfig );
928 return jsonObject;
929 }
930
931 private static JSONObject _fromJSONString( JSONString string, JsonConfig jsonConfig ) {
932 return _fromJSONTokener( new JSONTokener( string.toJSONString() ), jsonConfig );
933 }
934
935 private static JSONObject _fromJSONTokener( JSONTokener tokener, JsonConfig jsonConfig ) {
936
937 try{
938 char c;
939 String key;
940 Object value;
941
942 if( tokener.matches( "null.*" ) ){
943 fireObjectStartEvent( jsonConfig );
944 fireObjectEndEvent( jsonConfig );
945 return new JSONObject( true );
946 }
947
948 if( tokener.nextClean() != '{' ){
949 throw tokener.syntaxError( "A JSONObject text must begin with '{'" );
950 }
951 fireObjectStartEvent( jsonConfig );
952
953 Collection exclusions = jsonConfig.getMergedExcludes();
954 PropertyFilter jsonPropertyFilter = jsonConfig.getJsonPropertyFilter();
955 JSONObject jsonObject = new JSONObject();
956 for( ;; ){
957 c = tokener.nextClean();
958 switch( c ){
959 case 0:
960 throw tokener.syntaxError( "A JSONObject text must end with '}'" );
961 case '}':
962 fireObjectEndEvent( jsonConfig );
963 return jsonObject;
964 default:
965 tokener.back();
966 key = tokener.nextValue( jsonConfig )
967 .toString();
968 }
969
970
971
972
973
974 c = tokener.nextClean();
975 if( c == '=' ){
976 if( tokener.next() != '>' ){
977 tokener.back();
978 }
979 }else if( c != ':' ){
980 throw tokener.syntaxError( "Expected a ':' after a key" );
981 }
982
983 char peek = tokener.peek();
984 boolean quoted = peek == '"' || peek == '\'';
985 Object v = tokener.nextValue( jsonConfig );
986 if( quoted || !JSONUtils.isFunctionHeader( v ) ){
987 if( exclusions.contains( key ) ){
988 switch( tokener.nextClean() ){
989 case ';':
990 case ',':
991 if( tokener.nextClean() == '}' ){
992 fireObjectEndEvent( jsonConfig );
993 return jsonObject;
994 }
995 tokener.back();
996 break;
997 case '}':
998 fireObjectEndEvent( jsonConfig );
999 return jsonObject;
1000 default:
1001 throw tokener.syntaxError( "Expected a ',' or '}'" );
1002 }
1003 continue;
1004 }
1005 if( jsonPropertyFilter == null || !jsonPropertyFilter.apply( tokener, key, v ) ){
1006 if( quoted && v instanceof String && (JSONUtils.mayBeJSON( (String) v ) || JSONUtils.isFunction( v ))){
1007 v = JSONUtils.DOUBLE_QUOTE + v + JSONUtils.DOUBLE_QUOTE;
1008 }
1009 if( jsonObject.properties.containsKey( key ) ){
1010 jsonObject.accumulate( key, v, jsonConfig );
1011 firePropertySetEvent( key, v, true, jsonConfig );
1012 }else{
1013 jsonObject.element( key, v, jsonConfig );
1014 firePropertySetEvent( key, v, false, jsonConfig );
1015 }
1016 }
1017 }else{
1018
1019 String params = JSONUtils.getFunctionParams( (String) v );
1020
1021 int i = 0;
1022 StringBuffer sb = new StringBuffer();
1023 for( ;; ){
1024 char ch = tokener.next();
1025 if( ch == 0 ){
1026 break;
1027 }
1028 if( ch == '{' ){
1029 i++;
1030 }
1031 if( ch == '}' ){
1032 i--;
1033 }
1034 sb.append( ch );
1035 if( i == 0 ){
1036 break;
1037 }
1038 }
1039 if( i != 0 ){
1040 throw tokener.syntaxError( "Unbalanced '{' or '}' on prop: " + v );
1041 }
1042
1043 String text = sb.toString();
1044 text = text.substring( 1, text.length() - 1 )
1045 .trim();
1046 value = new JSONFunction(
1047 (params != null) ? StringUtils.split( params, "," ) : null, text );
1048 if( jsonPropertyFilter == null || !jsonPropertyFilter.apply( tokener, key, value ) ){
1049 if( jsonObject.properties.containsKey( key ) ){
1050 jsonObject.accumulate( key, value, jsonConfig );
1051 firePropertySetEvent( key, value, true, jsonConfig );
1052 }else{
1053 jsonObject.element( key, value, jsonConfig );
1054 firePropertySetEvent( key, value, false, jsonConfig );
1055 }
1056 }
1057 }
1058
1059
1060
1061
1062
1063 switch( tokener.nextClean() ){
1064 case ';':
1065 case ',':
1066 if( tokener.nextClean() == '}' ){
1067 fireObjectEndEvent( jsonConfig );
1068 return jsonObject;
1069 }
1070 tokener.back();
1071 break;
1072 case '}':
1073 fireObjectEndEvent( jsonConfig );
1074 return jsonObject;
1075 default:
1076 throw tokener.syntaxError( "Expected a ',' or '}'" );
1077 }
1078 }
1079 }catch( JSONException jsone ){
1080 fireErrorEvent( jsone, jsonConfig );
1081 throw jsone;
1082 }
1083 }
1084
1085 private static JSONObject _fromMap( Map map, JsonConfig jsonConfig ) {
1086 if( map == null ){
1087 fireObjectStartEvent( jsonConfig );
1088 fireObjectEndEvent( jsonConfig );
1089 return new JSONObject( true );
1090 }
1091
1092 if( !addInstance( map ) ){
1093 try{
1094 return jsonConfig.getCycleDetectionStrategy()
1095 .handleRepeatedReferenceAsObject( map );
1096 }catch( JSONException jsone ){
1097 removeInstance( map );
1098 fireErrorEvent( jsone, jsonConfig );
1099 throw jsone;
1100 }catch( RuntimeException e ){
1101 removeInstance( map );
1102 JSONException jsone = new JSONException( e );
1103 fireErrorEvent( jsone, jsonConfig );
1104 throw jsone;
1105 }
1106 }
1107 fireObjectStartEvent( jsonConfig );
1108
1109 Collection exclusions = jsonConfig.getMergedExcludes();
1110 JSONObject jsonObject = new JSONObject();
1111 PropertyFilter jsonPropertyFilter = jsonConfig.getJsonPropertyFilter();
1112 try{
1113 for( Iterator entries = map.entrySet()
1114 .iterator(); entries.hasNext(); ){
1115 boolean bypass = false;
1116 Map.Entry entry = (Map.Entry) entries.next();
1117 Object k = entry.getKey();
1118 if( k == null ){
1119 throw new JSONException("JSON keys cannot be null.");
1120 }
1121 if( !(k instanceof String) && !jsonConfig.isAllowNonStringKeys() ) {
1122 throw new ClassCastException("JSON keys must be strings.");
1123 }
1124 String key = String.valueOf( k );
1125 if( "null".equals( key )){
1126 throw new NullPointerException("JSON keys must not be null nor the 'null' string.");
1127 }
1128 if( exclusions.contains( key ) ){
1129 continue;
1130 }
1131 Object value = entry.getValue();
1132 if( jsonPropertyFilter != null && jsonPropertyFilter.apply( map, key, value ) ){
1133 continue;
1134 }
1135 if( value != null ){
1136 JsonValueProcessor jsonValueProcessor = jsonConfig.findJsonValueProcessor(
1137 value.getClass(), key );
1138 if( jsonValueProcessor != null ){
1139 value = jsonValueProcessor.processObjectValue( key, value, jsonConfig );
1140 bypass = true;
1141 if( !JsonVerifier.isValidJsonValue( value ) ){
1142 throw new JSONException( "Value is not a valid JSON value. " + value );
1143 }
1144 }
1145 setValue( jsonObject, key, value, value.getClass(), jsonConfig, bypass );
1146 }else{
1147 if( jsonObject.properties.containsKey( key ) ){
1148 jsonObject.accumulate( key, JSONNull.getInstance() );
1149 firePropertySetEvent( key, JSONNull.getInstance(), true, jsonConfig );
1150 }else{
1151 jsonObject.element( key, JSONNull.getInstance() );
1152 firePropertySetEvent( key, JSONNull.getInstance(), false, jsonConfig );
1153 }
1154 }
1155 }
1156 }catch( JSONException jsone ){
1157 removeInstance( map );
1158 fireErrorEvent( jsone, jsonConfig );
1159 throw jsone;
1160 }catch( RuntimeException e ){
1161 removeInstance( map );
1162 JSONException jsone = new JSONException( e );
1163 fireErrorEvent( jsone, jsonConfig );
1164 throw jsone;
1165 }
1166
1167 removeInstance( map );
1168 fireObjectEndEvent( jsonConfig );
1169 return jsonObject;
1170 }
1171
1172 private static JSONObject _fromString( String str, JsonConfig jsonConfig ) {
1173 if( str == null || "null".equals( str ) ){
1174 fireObjectStartEvent( jsonConfig );
1175 fireObjectEndEvent( jsonConfig );
1176 return new JSONObject( true );
1177 }
1178 return _fromJSONTokener( new JSONTokener( str ), jsonConfig );
1179 }
1180
1181 private static Object convertPropertyValueToArray( String key, Object value, Class targetType,
1182 JsonConfig jsonConfig, Map classMap ) {
1183 Class innerType = JSONUtils.getInnerComponentType( targetType );
1184 Class targetInnerType = findTargetClass( key, classMap );
1185 if( innerType.equals( Object.class ) && targetInnerType != null
1186 && !targetInnerType.equals( Object.class ) ){
1187 innerType = targetInnerType;
1188 }
1189 JsonConfig jsc = jsonConfig.copy();
1190 jsc.setRootClass( innerType );
1191 jsc.setClassMap( classMap );
1192 Object array = JSONArray.toArray( (JSONArray) value, jsc );
1193 if( innerType.isPrimitive() || JSONUtils.isNumber( innerType )
1194 || Boolean.class.isAssignableFrom( innerType ) || JSONUtils.isString( innerType ) ){
1195 array = JSONUtils.getMorpherRegistry()
1196 .morph( Array.newInstance( innerType, 0 )
1197 .getClass(), array );
1198 }else if( !array.getClass()
1199 .equals( targetType ) ){
1200 if( !targetType.equals( Object.class ) ){
1201 Morpher morpher = JSONUtils.getMorpherRegistry()
1202 .getMorpherFor( Array.newInstance( innerType, 0 )
1203 .getClass() );
1204 if( IdentityObjectMorpher.getInstance()
1205 .equals( morpher ) ){
1206 ObjectArrayMorpher beanMorpher = new ObjectArrayMorpher( new BeanMorpher( innerType,
1207 JSONUtils.getMorpherRegistry() ) );
1208 JSONUtils.getMorpherRegistry()
1209 .registerMorpher( beanMorpher );
1210 }
1211 array = JSONUtils.getMorpherRegistry()
1212 .morph( Array.newInstance( innerType, 0 )
1213 .getClass(), array );
1214 }
1215 }
1216 return array;
1217 }
1218
1219 private static List convertPropertyValueToList( String key, Object value, JsonConfig jsonConfig,
1220 String name, Map classMap ) {
1221 Class targetClass = findTargetClass( key, classMap );
1222 targetClass = targetClass == null ? findTargetClass( name, classMap ) : targetClass;
1223 JsonConfig jsc = jsonConfig.copy();
1224 jsc.setRootClass( targetClass );
1225 jsc.setClassMap( classMap );
1226 List list = (List) JSONArray.toCollection( (JSONArray) value, jsc );
1227 return list;
1228 }
1229
1230 private static Collection convertPropertyValueToCollection( String key, Object value, JsonConfig jsonConfig,
1231 String name, Map classMap, Class collectionType ) {
1232 Class targetClass = findTargetClass( key, classMap );
1233 targetClass = targetClass == null ? findTargetClass( name, classMap ) : targetClass;
1234 JsonConfig jsc = jsonConfig.copy();
1235 jsc.setRootClass( targetClass );
1236 jsc.setClassMap( classMap );
1237 jsc.setCollectionType( collectionType );
1238 return JSONArray.toCollection( (JSONArray) value, jsc );
1239 }
1240
1241
1242
1243
1244
1245 private static Class findTargetClass( String key, Map classMap ) {
1246
1247 Class targetClass = (Class) classMap.get( key );
1248 if( targetClass == null ){
1249
1250
1251
1252 for( Iterator i = classMap.entrySet()
1253 .iterator(); i.hasNext(); ){
1254 Map.Entry entry = (Map.Entry) i.next();
1255 if( RegexpUtils.getMatcher( (String) entry.getKey() )
1256 .matches( key ) ){
1257 targetClass = (Class) entry.getValue();
1258 break;
1259 }
1260 }
1261 }
1262
1263 return targetClass;
1264 }
1265
1266 private static boolean isTransientField( String name, Class beanClass ) {
1267 try{
1268 return isTransientField(beanClass.getDeclaredField( name ));
1269 }catch( Exception e ){
1270
1271 }
1272 return false;
1273 }
1274
1275 private static boolean isTransientField( Field field ) {
1276 return (field.getModifiers() & Modifier.TRANSIENT) == Modifier.TRANSIENT;
1277 }
1278
1279 private static Object morphPropertyValue( String key, Object value, Class type, Class targetType ) {
1280 Morpher morpher = JSONUtils.getMorpherRegistry()
1281 .getMorpherFor( targetType );
1282 if( IdentityObjectMorpher.getInstance()
1283 .equals( morpher ) ){
1284 log.warn( "Can't transform property '" + key + "' from " + type.getName() + " into "
1285 + targetType.getName() + ". Will register a default BeanMorpher" );
1286 JSONUtils.getMorpherRegistry()
1287 .registerMorpher( new BeanMorpher( targetType, JSONUtils.getMorpherRegistry() ) );
1288 }
1289 value = JSONUtils.getMorpherRegistry()
1290 .morph( targetType, value );
1291 return value;
1292 }
1293
1294
1295
1296
1297
1298 private static void setProperty( Object bean, String key, Object value, JsonConfig jsonConfig )
1299 throws Exception {
1300 PropertySetStrategy propertySetStrategy = jsonConfig.getPropertySetStrategy() != null ? jsonConfig.getPropertySetStrategy()
1301 : PropertySetStrategy.DEFAULT;
1302 propertySetStrategy.setProperty( bean, key, value, jsonConfig );
1303 }
1304
1305 private static void setValue( JSONObject jsonObject, String key, Object value, Class type,
1306 JsonConfig jsonConfig, boolean bypass ) {
1307 boolean accumulated = false;
1308 if( value == null ){
1309 value = jsonConfig.findDefaultValueProcessor( type )
1310 .getDefaultValue( type );
1311 if( !JsonVerifier.isValidJsonValue( value ) ){
1312 throw new JSONException( "Value is not a valid JSON value. " + value );
1313 }
1314 }
1315 if( jsonObject.properties.containsKey( key ) ){
1316 if( String.class.isAssignableFrom( type ) ){
1317 Object o = jsonObject.opt( key );
1318 if( o instanceof JSONArray ){
1319 ((JSONArray) o).addString( (String) value );
1320 }else{
1321 jsonObject.properties.put( key, new JSONArray().element( o )
1322 .addString( (String) value ) );
1323 }
1324 }else{
1325 jsonObject.accumulate( key, value, jsonConfig );
1326 }
1327 accumulated = true;
1328 }else{
1329 if( bypass || String.class.isAssignableFrom( type ) ){
1330 jsonObject.properties.put( key, value );
1331 }else{
1332 jsonObject.setInternal( key, value, jsonConfig );
1333 }
1334 }
1335
1336 value = jsonObject.opt( key );
1337 if( accumulated ){
1338 JSONArray array = (JSONArray) value;
1339 value = array.get( array.size() - 1 );
1340 }
1341 firePropertySetEvent( key, value, accumulated, jsonConfig );
1342 }
1343
1344
1345
1346
1347 private boolean nullObject;
1348
1349
1350
1351
1352 private Map properties;
1353
1354
1355
1356
1357 public JSONObject() {
1358 this.properties = new ListOrderedMap();
1359 }
1360
1361
1362
1363
1364 public JSONObject( boolean isNull ) {
1365 this();
1366 this.nullObject = isNull;
1367 }
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382 public JSONObject accumulate( String key, boolean value ) {
1383 return _accumulate( key, value ? Boolean.TRUE : Boolean.FALSE, new JsonConfig() );
1384 }
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399 public JSONObject accumulate( String key, double value ) {
1400 return _accumulate( key, new Double( value ), new JsonConfig() );
1401 }
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416 public JSONObject accumulate( String key, int value ) {
1417 return _accumulate( key, new Integer( value ), new JsonConfig() );
1418 }
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433 public JSONObject accumulate( String key, long value ) {
1434 return _accumulate( key, new Long( value ), new JsonConfig() );
1435 }
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450 public JSONObject accumulate( String key, Object value ) {
1451 return _accumulate( key, value, new JsonConfig() );
1452 }
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467 public JSONObject accumulate( String key, Object value, JsonConfig jsonConfig ) {
1468 return _accumulate( key, value, jsonConfig );
1469 }
1470
1471 public void accumulateAll( Map map ) {
1472 accumulateAll( map, new JsonConfig() );
1473 }
1474
1475 public void accumulateAll( Map map, JsonConfig jsonConfig ) {
1476 if( map instanceof JSONObject ){
1477 for( Iterator entries = map.entrySet()
1478 .iterator(); entries.hasNext(); ){
1479 Map.Entry entry = (Map.Entry) entries.next();
1480 String key = (String) entry.getKey();
1481 Object value = entry.getValue();
1482 accumulate( key, value, jsonConfig );
1483 }
1484 }else{
1485 for( Iterator entries = map.entrySet()
1486 .iterator(); entries.hasNext(); ){
1487 Map.Entry entry = (Map.Entry) entries.next();
1488 String key = String.valueOf( entry.getKey() );
1489 Object value = entry.getValue();
1490 accumulate( key, value, jsonConfig );
1491 }
1492 }
1493 }
1494
1495 public void clear() {
1496 properties.clear();
1497 }
1498
1499 public int compareTo( Object obj ) {
1500 if( obj != null && (obj instanceof JSONObject) ){
1501 JSONObject other = (JSONObject) obj;
1502 int size1 = size();
1503 int size2 = other.size();
1504 if( size1 < size2 ){
1505 return -1;
1506 }else if( size1 > size2 ){
1507 return 1;
1508 }else if( this.equals( other ) ){
1509 return 0;
1510 }
1511 }
1512 return -1;
1513 }
1514
1515 public boolean containsKey( Object key ) {
1516 return properties.containsKey( key );
1517 }
1518
1519 public boolean containsValue( Object value ) {
1520 return containsValue( value, new JsonConfig() );
1521 }
1522
1523 public boolean containsValue( Object value, JsonConfig jsonConfig ) {
1524 try{
1525 value = processValue( value, jsonConfig );
1526 }catch( JSONException e ){
1527 return false;
1528 }
1529 return properties.containsValue( value );
1530 }
1531
1532
1533
1534
1535
1536
1537
1538 public JSONObject discard( String key ) {
1539 verifyIsNull();
1540 this.properties.remove( key );
1541 return this;
1542 }
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552 public JSONObject element( String key, boolean value ) {
1553 verifyIsNull();
1554 return element( key, value ? Boolean.TRUE : Boolean.FALSE );
1555 }
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566 public JSONObject element( String key, Collection value ) {
1567 return element( key, value, new JsonConfig() );
1568 }
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579 public JSONObject element( String key, Collection value, JsonConfig jsonConfig ) {
1580 verifyIsNull();
1581 if( !(value instanceof JSONArray) ){
1582 value = JSONArray.fromObject( value, jsonConfig );
1583 }
1584 return setInternal( key, value, jsonConfig );
1585 }
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595 public JSONObject element( String key, double value ) {
1596 verifyIsNull();
1597 Double d = new Double( value );
1598 JSONUtils.testValidity( d );
1599 return element( key, d );
1600 }
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610 public JSONObject element( String key, int value ) {
1611 verifyIsNull();
1612 return element( key, new Integer( value ) );
1613 }
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623 public JSONObject element( String key, long value ) {
1624 verifyIsNull();
1625 return element( key, new Long( value ) );
1626 }
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637 public JSONObject element( String key, Map value ) {
1638 return element( key, value, new JsonConfig() );
1639 }
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650 public JSONObject element( String key, Map value, JsonConfig jsonConfig ) {
1651 verifyIsNull();
1652 if( value instanceof JSONObject ){
1653 return setInternal( key, value, jsonConfig );
1654 }else{
1655 return element( key, JSONObject.fromObject( value, jsonConfig ), jsonConfig );
1656 }
1657 }
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672 public JSONObject element( String key, Object value ) {
1673 return element( key, value, new JsonConfig() );
1674 }
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689 public JSONObject element( String key, Object value, JsonConfig jsonConfig ) {
1690 verifyIsNull();
1691 if( key == null ){
1692 throw new JSONException( "Null key." );
1693 }
1694 if( value != null ){
1695 value = processValue( key, value, jsonConfig );
1696 _setInternal( key, value, jsonConfig );
1697 }else{
1698 remove( key );
1699 }
1700 return this;
1701 }
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714 public JSONObject elementOpt( String key, Object value ) {
1715 return elementOpt( key, value, new JsonConfig() );
1716 }
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729 public JSONObject elementOpt( String key, Object value, JsonConfig jsonConfig ) {
1730 verifyIsNull();
1731 if( key != null && value != null ){
1732 element( key, value, jsonConfig );
1733 }
1734 return this;
1735 }
1736
1737 public Set entrySet() {
1738 return Collections.unmodifiableSet( properties.entrySet() );
1739 }
1740
1741 public boolean equals( Object obj ) {
1742 if( obj == this ){
1743 return true;
1744 }
1745 if( obj == null ){
1746 return false;
1747 }
1748
1749 if( !(obj instanceof JSONObject) ){
1750 return false;
1751 }
1752
1753 JSONObject other = (JSONObject) obj;
1754
1755 if( isNullObject() ){
1756 if( other.isNullObject() ){
1757 return true;
1758 }else{
1759 return false;
1760 }
1761 }else{
1762 if( other.isNullObject() ){
1763 return false;
1764 }
1765 }
1766
1767 if( other.size() != size() ){
1768 return false;
1769 }
1770
1771 for( Iterator keys = properties.keySet()
1772 .iterator(); keys.hasNext(); ){
1773 String key = (String) keys.next();
1774 if( !other.properties.containsKey( key ) ){
1775 return false;
1776 }
1777 Object o1 = properties.get( key );
1778 Object o2 = other.properties.get( key );
1779
1780 if( JSONNull.getInstance()
1781 .equals( o1 ) ){
1782 if( JSONNull.getInstance()
1783 .equals( o2 ) ){
1784 continue;
1785 }else{
1786 return false;
1787 }
1788 }else{
1789 if( JSONNull.getInstance()
1790 .equals( o2 ) ){
1791 return false;
1792 }
1793 }
1794
1795 if( o1 instanceof String && o2 instanceof JSONFunction ){
1796 if( !o1.equals( String.valueOf( o2 ) ) ){
1797 return false;
1798 }
1799 }else if( o1 instanceof JSONFunction && o2 instanceof String ){
1800 if( !o2.equals( String.valueOf( o1 ) ) ){
1801 return false;
1802 }
1803 }else if( o1 instanceof JSONObject && o2 instanceof JSONObject ){
1804 if( !o1.equals( o2 ) ){
1805 return false;
1806 }
1807 }else if( o1 instanceof JSONArray && o2 instanceof JSONArray ){
1808 if( !o1.equals( o2 ) ){
1809 return false;
1810 }
1811 }else if( o1 instanceof JSONFunction && o2 instanceof JSONFunction ){
1812 if( !o1.equals( o2 ) ){
1813 return false;
1814 }
1815 }else{
1816 if( o1 instanceof String ){
1817 if( !o1.equals( String.valueOf( o2 ) ) ){
1818 return false;
1819 }
1820 }else if( o2 instanceof String ){
1821 if( !o2.equals( String.valueOf( o1 ) ) ){
1822 return false;
1823 }
1824 }else{
1825 Morpher m1 = JSONUtils.getMorpherRegistry()
1826 .getMorpherFor( o1.getClass() );
1827 Morpher m2 = JSONUtils.getMorpherRegistry()
1828 .getMorpherFor( o2.getClass() );
1829 if( m1 != null && m1 != IdentityObjectMorpher.getInstance() ){
1830 if( !o1.equals( JSONUtils.getMorpherRegistry()
1831 .morph( o1.getClass(), o2 ) ) ){
1832 return false;
1833 }
1834 }else if( m2 != null && m2 != IdentityObjectMorpher.getInstance() ){
1835 if( !JSONUtils.getMorpherRegistry()
1836 .morph( o1.getClass(), o1 )
1837 .equals( o2 ) ){
1838 return false;
1839 }
1840 }else{
1841 if( !o1.equals( o2 ) ){
1842 return false;
1843 }
1844 }
1845 }
1846 }
1847 }
1848 return true;
1849 }
1850
1851 public Object get( Object key ) {
1852 if( key instanceof String ){
1853 return get( (String) key );
1854 }
1855 return null;
1856 }
1857
1858
1859
1860
1861
1862
1863
1864
1865 public Object get( String key ) {
1866 verifyIsNull();
1867 return this.properties.get( key );
1868 }
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878 public boolean getBoolean( String key ) {
1879 verifyIsNull();
1880 Object o = get( key );
1881 if( o != null ){
1882 if( o.equals( Boolean.FALSE )
1883 || (o instanceof String && ((String) o).equalsIgnoreCase( "false" )) ){
1884 return false;
1885 }else if( o.equals( Boolean.TRUE )
1886 || (o instanceof String && ((String) o).equalsIgnoreCase( "true" )) ){
1887 return true;
1888 }
1889 }
1890 throw new JSONException( "JSONObject[" + JSONUtils.quote( key ) + "] is not a Boolean." );
1891 }
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901 public double getDouble( String key ) {
1902 verifyIsNull();
1903 Object o = get( key );
1904 if( o != null ){
1905 try{
1906 return o instanceof Number ? ((Number) o).doubleValue()
1907 : Double.parseDouble( (String) o );
1908 }catch( Exception e ){
1909 throw new JSONException( "JSONObject[" + JSONUtils.quote( key ) + "] is not a number." );
1910 }
1911 }
1912 throw new JSONException( "JSONObject[" + JSONUtils.quote( key ) + "] is not a number." );
1913 }
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924 public int getInt( String key ) {
1925 verifyIsNull();
1926 Object o = get( key );
1927 if( o != null ){
1928 return o instanceof Number ? ((Number) o).intValue() : (int) getDouble( key );
1929 }
1930 throw new JSONException( "JSONObject[" + JSONUtils.quote( key ) + "] is not a number." );
1931 }
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941 public JSONArray getJSONArray( String key ) {
1942 verifyIsNull();
1943 Object o = get( key );
1944 if( o != null && o instanceof JSONArray ){
1945 return (JSONArray) o;
1946 }
1947 throw new JSONException( "JSONObject[" + JSONUtils.quote( key ) + "] is not a JSONArray." );
1948 }
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958 public JSONObject getJSONObject( String key ) {
1959 verifyIsNull();
1960 Object o = get( key );
1961 if( JSONNull.getInstance()
1962 .equals( o ) ){
1963 return new JSONObject( true );
1964 }else if( o instanceof JSONObject ){
1965 return (JSONObject) o;
1966 }
1967 throw new JSONException( "JSONObject[" + JSONUtils.quote( key ) + "] is not a JSONObject." );
1968 }
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979 public long getLong( String key ) {
1980 verifyIsNull();
1981 Object o = get( key );
1982 if( o != null ){
1983 return o instanceof Number ? ((Number) o).longValue() : (long) getDouble( key );
1984 }
1985 throw new JSONException( "JSONObject[" + JSONUtils.quote( key ) + "] is not a number." );
1986 }
1987
1988
1989
1990
1991
1992
1993
1994
1995 public String getString( String key ) {
1996 verifyIsNull();
1997 Object o = get( key );
1998 if( o != null ){
1999 return o.toString();
2000 }
2001 throw new JSONException( "JSONObject[" + JSONUtils.quote( key ) + "] not found." );
2002 }
2003
2004
2005
2006
2007
2008
2009
2010 public boolean has( String key ) {
2011 verifyIsNull();
2012 return this.properties.containsKey( key );
2013 }
2014
2015 public int hashCode() {
2016 int hashcode = 19;
2017 if( isNullObject() ){
2018 return hashcode + JSONNull.getInstance()
2019 .hashCode();
2020 }
2021 for( Iterator entries = properties.entrySet()
2022 .iterator(); entries.hasNext(); ){
2023 Map.Entry entry = (Map.Entry) entries.next();
2024 Object key = entry.getKey();
2025 Object value = entry.getValue();
2026 hashcode += key.hashCode() + JSONUtils.hashCode( value );
2027 }
2028 return hashcode;
2029 }
2030
2031 public boolean isArray() {
2032 return false;
2033 }
2034
2035 public boolean isEmpty() {
2036
2037 return this.properties.isEmpty();
2038 }
2039
2040
2041
2042
2043 public boolean isNullObject() {
2044 return nullObject;
2045 }
2046
2047
2048
2049
2050
2051
2052 public Iterator keys() {
2053 verifyIsNull();
2054 return keySet().iterator();
2055 }
2056
2057 public Set keySet() {
2058 return Collections.unmodifiableSet( properties.keySet() );
2059 }
2060
2061
2062
2063
2064
2065
2066
2067
2068 public JSONArray names() {
2069 return names( new JsonConfig() );
2070 }
2071
2072
2073
2074
2075
2076
2077
2078
2079 public JSONArray names( JsonConfig jsonConfig ) {
2080 verifyIsNull();
2081 JSONArray ja = new JSONArray();
2082 Iterator keys = keys();
2083 while( keys.hasNext() ){
2084 ja.element( keys.next(), jsonConfig );
2085 }
2086 return ja;
2087 }
2088
2089
2090
2091
2092
2093
2094
2095 public Object opt( String key ) {
2096 verifyIsNull();
2097 return key == null ? null : this.properties.get( key );
2098 }
2099
2100
2101
2102
2103
2104
2105
2106
2107 public boolean optBoolean( String key ) {
2108 verifyIsNull();
2109 return optBoolean( key, false );
2110 }
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121 public boolean optBoolean( String key, boolean defaultValue ) {
2122 verifyIsNull();
2123 try{
2124 return getBoolean( key );
2125 }catch( Exception e ){
2126 return defaultValue;
2127 }
2128 }
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138 public double optDouble( String key ) {
2139 verifyIsNull();
2140 return optDouble( key, Double.NaN );
2141 }
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152 public double optDouble( String key, double defaultValue ) {
2153 verifyIsNull();
2154 try{
2155 Object o = opt( key );
2156 return o instanceof Number ? ((Number) o).doubleValue()
2157 : new Double( (String) o ).doubleValue();
2158 }catch( Exception e ){
2159 return defaultValue;
2160 }
2161 }
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171 public int optInt( String key ) {
2172 verifyIsNull();
2173 return optInt( key, 0 );
2174 }
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185 public int optInt( String key, int defaultValue ) {
2186 verifyIsNull();
2187 try{
2188 return getInt( key );
2189 }catch( Exception e ){
2190 return defaultValue;
2191 }
2192 }
2193
2194
2195
2196
2197
2198
2199
2200
2201 public JSONArray optJSONArray( String key ) {
2202 verifyIsNull();
2203 Object o = opt( key );
2204 return o instanceof JSONArray ? (JSONArray) o : null;
2205 }
2206
2207
2208
2209
2210
2211
2212
2213
2214 public JSONObject optJSONObject( String key ) {
2215 verifyIsNull();
2216 Object o = opt( key );
2217 return o instanceof JSONObject ? (JSONObject) o : null;
2218 }
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228 public long optLong( String key ) {
2229 verifyIsNull();
2230 return optLong( key, 0 );
2231 }
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242 public long optLong( String key, long defaultValue ) {
2243 verifyIsNull();
2244 try{
2245 return getLong( key );
2246 }catch( Exception e ){
2247 return defaultValue;
2248 }
2249 }
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259 public String optString( String key ) {
2260 verifyIsNull();
2261 return optString( key, "" );
2262 }
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272 public String optString( String key, String defaultValue ) {
2273 verifyIsNull();
2274 Object o = opt( key );
2275 return o != null ? o.toString() : defaultValue;
2276 }
2277
2278 public Object put( Object key, Object value ) {
2279 if( key == null ){
2280 throw new IllegalArgumentException( "key is null." );
2281 }
2282 Object previous = properties.get( key );
2283 element( String.valueOf( key ), value );
2284 return previous;
2285 }
2286
2287 public void putAll( Map map ) {
2288 putAll( map, new JsonConfig() );
2289 }
2290
2291 public void putAll( Map map, JsonConfig jsonConfig ) {
2292 if( map instanceof JSONObject ){
2293 for( Iterator entries = map.entrySet()
2294 .iterator(); entries.hasNext(); ){
2295 Map.Entry entry = (Map.Entry) entries.next();
2296 String key = (String) entry.getKey();
2297 Object value = entry.getValue();
2298 this.properties.put( key, value );
2299 }
2300 }else{
2301 for( Iterator entries = map.entrySet()
2302 .iterator(); entries.hasNext(); ){
2303 Map.Entry entry = (Map.Entry) entries.next();
2304 String key = String.valueOf( entry.getKey() );
2305 Object value = entry.getValue();
2306 element( key, value, jsonConfig );
2307 }
2308 }
2309 }
2310
2311 public Object remove( Object key ) {
2312 return properties.remove( key );
2313 }
2314
2315
2316
2317
2318
2319
2320
2321
2322 public Object remove( String key ) {
2323 verifyIsNull();
2324 return this.properties.remove( key );
2325 }
2326
2327
2328
2329
2330
2331
2332 public int size() {
2333
2334 return this.properties.size();
2335 }
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346 public JSONArray toJSONArray( JSONArray names ) {
2347 verifyIsNull();
2348 if( names == null || names.size() == 0 ){
2349 return null;
2350 }
2351 JSONArray ja = new JSONArray();
2352 for( int i = 0; i < names.size(); i += 1 ){
2353 ja.element( this.opt( names.getString( i ) ) );
2354 }
2355 return ja;
2356 }
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370 public String toString() {
2371 if( isNullObject() ){
2372 return JSONNull.getInstance()
2373 .toString();
2374 }
2375 try{
2376 Iterator keys = keys();
2377 StringBuffer sb = new StringBuffer( "{" );
2378
2379 while( keys.hasNext() ){
2380 if( sb.length() > 1 ){
2381 sb.append( ',' );
2382 }
2383 Object o = keys.next();
2384 sb.append( JSONUtils.quote( o.toString() ) );
2385 sb.append( ':' );
2386 sb.append( JSONUtils.valueToString( this.properties.get( o ) ) );
2387 }
2388 sb.append( '}' );
2389 return sb.toString();
2390 }catch( Exception e ){
2391 return null;
2392 }
2393 }
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408 public String toString( int indentFactor ) {
2409 if( isNullObject() ){
2410 return JSONNull.getInstance()
2411 .toString();
2412 }
2413 if( indentFactor == 0 ){
2414 return this.toString();
2415 }
2416 return toString( indentFactor, 0 );
2417 }
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432 public String toString( int indentFactor, int indent ) {
2433 if( isNullObject() ){
2434 return JSONNull.getInstance()
2435 .toString();
2436 }
2437 int i;
2438 int n = size();
2439 if( n == 0 ){
2440 return "{}";
2441 }
2442 if( indentFactor == 0 ){
2443 return this.toString();
2444 }
2445 Iterator keys = keys();
2446 StringBuffer sb = new StringBuffer( "{" );
2447 int newindent = indent + indentFactor;
2448 Object o;
2449 if( n == 1 ){
2450 o = keys.next();
2451 sb.append( JSONUtils.quote( o.toString() ) );
2452 sb.append( ": " );
2453 sb.append( JSONUtils.valueToString( this.properties.get( o ), indentFactor, indent ) );
2454 }else{
2455 while( keys.hasNext() ){
2456 o = keys.next();
2457 if( sb.length() > 1 ){
2458 sb.append( ",\n" );
2459 }else{
2460 sb.append( '\n' );
2461 }
2462 for( i = 0; i < newindent; i += 1 ){
2463 sb.append( ' ' );
2464 }
2465 sb.append( JSONUtils.quote( o.toString() ) );
2466 sb.append( ": " );
2467 sb.append( JSONUtils.valueToString( this.properties.get( o ), indentFactor, newindent ) );
2468 }
2469 if( sb.length() > 1 ){
2470 sb.append( '\n' );
2471 for( i = 0; i < indent; i += 1 ){
2472 sb.append( ' ' );
2473 }
2474 }
2475 for( i = 0; i < indent; i += 1 ){
2476 sb.insert( 0, ' ' );
2477 }
2478 }
2479 sb.append( '}' );
2480 return sb.toString();
2481 }
2482
2483 public Collection values() {
2484 return Collections.unmodifiableCollection( properties.values() );
2485 }
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496 public Writer write( Writer writer ) {
2497 try{
2498 if( isNullObject() ){
2499 writer.write( JSONNull.getInstance()
2500 .toString() );
2501 return writer;
2502 }
2503
2504 boolean b = false;
2505 Iterator keys = keys();
2506 writer.write( '{' );
2507
2508 while( keys.hasNext() ){
2509 if( b ){
2510 writer.write( ',' );
2511 }
2512 Object k = keys.next();
2513 writer.write( JSONUtils.quote( k.toString() ) );
2514 writer.write( ':' );
2515 Object v = this.properties.get( k );
2516 if( v instanceof JSONObject ){
2517 ((JSONObject) v).write( writer );
2518 }else if( v instanceof JSONArray ){
2519 ((JSONArray) v).write( writer );
2520 }else{
2521 writer.write( JSONUtils.valueToString( v ) );
2522 }
2523 b = true;
2524 }
2525 writer.write( '}' );
2526 return writer;
2527 }catch( IOException e ){
2528 throw new JSONException( e );
2529 }
2530 }
2531
2532 private JSONObject _accumulate( String key, Object value, JsonConfig jsonConfig ) {
2533 if( isNullObject() ){
2534 throw new JSONException( "Can't accumulate on null object" );
2535 }
2536
2537 if( !has( key ) ){
2538 setInternal( key, value, jsonConfig );
2539 }else{
2540 Object o = opt( key );
2541 if( o instanceof JSONArray ){
2542 ((JSONArray) o).element( value, jsonConfig );
2543 }else{
2544 setInternal( key, new JSONArray().element( o )
2545 .element( value, jsonConfig ), jsonConfig );
2546 }
2547 }
2548
2549 return this;
2550 }
2551
2552 protected Object _processValue( Object value, JsonConfig jsonConfig ) {
2553 if( value instanceof JSONTokener ) {
2554 return _fromJSONTokener( (JSONTokener) value, jsonConfig );
2555 }
2556 return super._processValue( value, jsonConfig );
2557 }
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570 private JSONObject _setInternal( String key, Object value, JsonConfig jsonConfig ) {
2571 verifyIsNull();
2572 if( key == null ){
2573 throw new JSONException( "Null key." );
2574 }
2575
2576 if( JSONUtils.isString( value ) && JSONUtils.mayBeJSON( String.valueOf( value ) ) ){
2577 this.properties.put( key, value );
2578 }else{
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588 if( CycleDetectionStrategy.IGNORE_PROPERTY_OBJ == value
2589 || CycleDetectionStrategy.IGNORE_PROPERTY_ARR == value ){
2590
2591 }else{
2592 this.properties.put( key, value );
2593 }
2594 }
2595
2596 return this;
2597 }
2598
2599 private Object processValue( Object value, JsonConfig jsonConfig ) {
2600 if( value != null ){
2601 JsonValueProcessor processor = jsonConfig.findJsonValueProcessor( value.getClass() );
2602 if( processor != null ){
2603 value = processor.processObjectValue( null, value, jsonConfig );
2604 if( !JsonVerifier.isValidJsonValue( value ) ){
2605 throw new JSONException( "Value is not a valid JSON value. " + value );
2606 }
2607 }
2608 }
2609 return _processValue( value, jsonConfig );
2610 }
2611
2612 private Object processValue( String key, Object value, JsonConfig jsonConfig ) {
2613 if( value != null ){
2614 JsonValueProcessor processor = jsonConfig.findJsonValueProcessor( value.getClass(), key );
2615 if( processor != null ){
2616 value = processor.processObjectValue( null, value, jsonConfig );
2617 if( !JsonVerifier.isValidJsonValue( value ) ){
2618 throw new JSONException( "Value is not a valid JSON value. " + value );
2619 }
2620 }
2621 }
2622 return _processValue( value, jsonConfig );
2623 }
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636 private JSONObject setInternal( String key, Object value, JsonConfig jsonConfig ) {
2637 return _setInternal( key, processValue( key, value, jsonConfig ), jsonConfig );
2638 }
2639
2640
2641
2642
2643 private void verifyIsNull() {
2644 if( isNullObject() ){
2645 throw new JSONException( "null object" );
2646 }
2647 }
2648 }