XStreamStringWriter - XStream support

  1. Instruction
  2. Simple Binding
  3. Binding to CommandBean-Property
  4. Convert all Model Values
    1. Convert all values of Model-Map by CustomEditor
    2. Convert specific value in Model-Map by CustomEditor
  5. Keep unconverted value type format
  6. Register a XStreamJsonWriterConfiguratorTemplate

Instruction

NEWS :
The XStreamJsonStringWriter is the integration of the XStream framework to Spring-Json View. It adds streaming capabilities to the json view, so it can be used for big command beans.

The binding capabilities are the same like the SojoJsonStringWriter or JsonlibJsonStringWriter

  1. You can bind a CustomEditor to Global value class types like java.util.Date

  2. You can bind a CustomEditor to Properties of the ComandBean located by the CommensBeanUtils-Syntax

  3. Optional: To any other object in the model like those added in the referenceData-method.

  4. The XStreamJsonStringWriter supports implizite and explicite collection property binding

    • implizite: bean.list.property: locates all properties of the collection from index 0-n

      and

    • explicite: bean.list[1].property: locates properties implicate Collection-Beans with EXPIZITE index
  5. You can keep unconverted values in different modes.

  6. You can configurate the the JSON rendering by adding xstream Anotations see Annotations Tutorial

  7. XStreamJsonWriterConfiguratorTemplate enables you to use some of the Features of XStream. For example tweaking the Output.

Attention
Keep in mind

Simple Binding

initBinder Source:
=================

@Override
protected void initBinder(HttpServletRequest request,  
                        ServletRequestDataBinder binder) throws Exception{
        SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
        CustomDateEditor editor = new CustomDateEditor(dateFormat, true);
        binder.registerCustomEditor(Date.class, editor);
}

Result:
=======

{model:
       {"command":{
                   "birthday":"30-01-2008", 
                   "marriage":"30-01-2008", 
                   "placeofbirth":"Sydney",
                   "age":"40",
                   "childs": "true"
                  }
       }
}

Binding to CommandBean-Property

Properties of the CommandBean are located by the CommonsBeanUtils-Syntax

initBinder Source: 
==================
@Override
protected void initBinder(HttpServletRequest request,  
                ServletRequestDataBinder binder) throws Exception{
        SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
        CustomDateEditor editor = new CustomDateEditor(dateFormat, true);
        binder.registerCustomEditor(Date.class, "birthday", editor);
}

Result:
======

{model:
       {"command":{
                      "birthday":"30-01-2008",
                      "marriage":"Wed Jan 30 00:00:00 GMT 2008",
                      "placeofbirth":"Sydney",
                      "age":"40",
                      "childs": "true"
                      }
           }
}

Convert all Model Values

The XStreamStringWriter does provide the optional conversion of non CommandBean-Values of the model map. You have to activate this feature by setting the convertAllMapValues property in the JsonWriter-Bean in the view.xml.

You can locate them by registering a CustomEditor for a field starting with (non_commandbean_key).

  • (name_in_model_map_key).property
  • (key).list[1].property
<beans>
    <bean name="jsonView" class="org.springframework.web.servlet.view.json.JsonView">
        <property name="jsonWriter"><ref bean="jsonWriter"/></property>
    </bean>
    
    <bean name="jsonWriter" 
          class="org.springframework.web.servlet.view.json.writer.xstream.XStreamJsonStringWriter">
        <property name="convertAllMapValues"><value>true</value></property>
    </bean>
</beans>

Convert all values in Model-Map by CustomEditor

initBinder Source:
==================
@Override
protected void initBinder(HttpServletRequest request,  
                ServletRequestDataBinder binder) throws Exception{
        SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
        CustomDateEditor editor = new CustomDateEditor(dateFormat, true);
        binder.registerCustomEditor(Date.class, editor);
}
        
Result:
=======

{model:
       {"signdate":"30-01-2008",
        "command":{
                   "birthday":"30-01-2008",
                   "marriage":"30-01-2008",
                   "placeofbirth":"Sydney",
                   "age":"40",
                   "childs": "true"
       }
}

Convert specific values in Model-Map by CustomEditor

initBinder Source:
==================
@Override
protected void initBinder(HttpServletRequest request,  
                ServletRequestDataBinder binder) throws Exception{
        SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
        CustomDateEditor editor = new CustomDateEditor(dateFormat, true);
        binder.registerCustomEditor(Date.class, "birthday", editor);
        binder.registerCustomEditor(Date.class, "(signdate)", editor);
}
        
Result:
=======

{model:
       {"signdate":"30-01-2008",
       "command":{
                   "birthday":"30-01-2008",
                   "marriage":"Wed Jan 30 00:00:00 GMT 2008",
                   "placeofbirth":"Sydney",
                   "age":"40",
                   "childs": "true"
       }}
}

Keep unconverted value type format

All values which are converted by an registered CustomEditor are rendered as a String. The spring jsl-view converts all other values of the model to strings too. The XStreamStringWriter keeps this behaviour by default. Some times it is very useful to know what type a particular unconverted value has. The JavaScript Object Notation specifys that numbers and booleans not quoted see http://www.json.org. The XStreamStringWriter is able to serialize unconverted values in 3 different modes.

  1. "NONE"-Mode (Default): serialize all values to strings.
  2. "BOOLEANS"-Mode: keep unconverted Boolean value type format like "flag":true
  3. "ALL"-Mode: keep all unconverted value type formats like "flag":true ore "number":2

Set the "keepValueTypesMode"-property in the spring-configuration

<beans>
    <bean name="jsonView" class="org.springframework.web.servlet.view.json.JsonView">
            <property name="jsonWriter"><ref bean="jsonWriter"/></property>
    </bean>
        
         <bean name="jsonWriter"  class="org.springframework.web.servlet.view.json.writer.xstream.XStreamJsonStringWriter"">
        <property name="keepValueTypesMode"><value>ALL</value></property>
    </bean>
</beans>

Result:
=======

{model:
       {"signdate":"30-01-2008",
        "command":{
                   "birthday":"30-01-1968",
                   "marriage":"Wed Jan 30 00:00:00 GMT 2008",
                   "placeofbirth":"Sydney",
                   "age":40,
                   "childs": true
       }}
}

Add XStream Annotation Support

You can configurate the the JSON rendering by adding xstream Anotations see Annotations Tutorial You can use following propertes to activate Annotation Support.

  1. enableAnnotationConf : Enable Annotation Configuration. Standart Class (CommandBean-Class ) which is be considerred for Annotation Configuration is the CommandBean-Class
  2. processAnnotationsForType : Overwrite the standart Class
  3. processAnnotationsForTypes : Overwrite the standart Classes.
  4. autodetectAnnotations: Add autodetection

Set the "keepValueTypesMode"-property in the spring-configuration

<beans>
    <bean name="jsonView" class="org.springframework.web.servlet.view.json.JsonView">
            <property name="jsonWriter"><ref bean="jsonWriter"/></property>
    </bean>
        
         <bean name="jsonWriter"  class="org.springframework.web.servlet.view.json.writer.xstream.XStreamJsonStringWriter"">
        <property name="enableAnnotationConf"><value>true</value></property>
    </bean>
</beans>

CommandBean
=======

public class SpringJsonForm {

        private String placeofbirth;
        
        @XStreamAlias("date")
        private Date birthday;
        
        private String placeofbirth;
        
        private Integer age;
        
        @XStreamOmitField
        private boolean childs;

        // setter and getter

}

Result:
=======

{model:
       {"signdate":"30-01-2008",
        "command":{
                   "date":"30-01-1968",
                   "marriage":"Wed Jan 30 00:00:00 GMT 2008",
                   "placeofbirth":"Sydney",
                   "age":40,
       }}
}

Register XStreamJsonWriterConfiguratorTemplates

If you want to use a XStreamJsonWriterConfiguratorTemplate, you have to

  1. set the "enableJsonConfigSupport"-property of the XStreamJsonStringWriter.
  2. implement the abstract "XStreamJsonWriterConfiguratorTemplate".
  3. register the XStreamJsonWriterConfiguratorTemplate at the JsonWriterConfiguratorTemplateRegistry.

It is recommended to register the XStreamJsonWriterConfiguratorTemplate in the initBinder method but you can register it in any controller method you can reach the request. This even could be the handleRequest method of an ControllerInterface implementation.

Set the "enableJsonConfigSupport"-property in the spring-configuration

<beans>
    <bean name="jsonView" class="org.springframework.web.servlet.view.json.JsonView">
            <property name="jsonWriter"><ref bean="jsonlibJsonWriter"/></property>
    </bean>
        
        <bean name="jsonWriter"  class="org.springframework.web.servlet.view.json.writer.xstream.XStreamJsonStringWriter">
        <property name="enableJsonConfigSupport"><value>true</value></property>
    </bean>
</beans>

Configuration : SpringJsonXStream

The SpringJsonXStream extends the com.thoughtworks.xstream.XStream object. SpringJsonXStream enables you to use some of the Features of XStream. For example tweaking the Output.

Please always use the SpringJsonXStreamBuilder to create a new SpringJsonXStream object. You have two functions to do thought:

  • public static SpringJsonXStream build(boolean convertAllMapValues, String keepValueTypesMode, String rootname)
  • public static SpringJsonXStream build(boolean convertAllMapValues, String keepValueTypesMode, String rootname, boolean prettyPrint)
function parameter Function Allowed Values Default Value
convertAllMapValues see 4. Convert all Model Values true, false false
keepValueTypesMode s.a Keep unconverted value type format. NONE, BOOLEANS, ALL NONE
rootname The JSON Stream generated by the XStreamJsonStringWriter has
an additional root element like {model:{command:[...]}}
A valide JSON Object property
name of type java.lang.String
model
prettyPrint converts the out put to a structured format true, false false
enableAnnotationConf enable Annotation Configuration true, false false
processAnnotationsForType
processAnnotationsForTypes
Class/es which should be considerred
for Annotation Configuration
Class
Class[]
CommandBean
Class
autodetectAnnotations Add autodetection for Annotation Configuration true, false false

Register the XStreamJsonWriterConfiguratorTemplates

initBinder Source:
==================
@Override
protected void initBinder(HttpServletRequest request,  ServletRequestDataBinder binder) throws Exception{
                
    JsonWriterConfiguratorTemplateRegistry registry = JsonWriterConfiguratorTemplateRegistry.load(request);             
    registry.registerConfiguratorTemplate(
         new XStreamJsonWriterConfiguratorTemplate(){
                @Override
                public SpringJsonXStream getSpringJsonXStream() {
                   
                   SpringJsonXStream xstream = SpringJsonXStreamBuilder.build(false, JsonStringWriter.MODE_KEEP_VALUETYPES_NONE, "model");
                   // rename property
                   xstream.aliasField("renamedsigndate", ComplexBean.class, "signdate");
                   // exclude property
                   xstream.omitField(ComplexBean.class, "age") 
                                   
                   return xstream;
                }
         }
   );
}
        
Result:
=======
{model:
       {"renamedsigndate":"30-01-2008",
       "command":{
                   "birthday":"30-01-1968",
                   "marriage":"Wed Jan 30 00:00:00 GMT 2008",
                   "placeofbirth":"Sydney",
                   "childs":"true"
       }}
}