views:

242

answers:

4

Hello,

I'm working on a project with JAXB but I run into a small problem with JAXB and the char datatype.

char gender = 'M';

Translates after marshalling into:

<gender>77</gender>

So I think that char is mapped to integer, but I simply want to map it to a String. How can I do this? Is it even possible?

+1  A: 

First thing i got in my mind :)

String gender = "M";
gedevan
+2  A: 

After some experimentation, there appears to be no way to configure JAXB to handle primitive chars properly. I'm having a hard time accepting it, though.

I've tried defining an XmlAdaptor to try and coerce it into a String, but the runtime seems to only accept adapters annotated on Object types, not primitives.

The only workaround I can think of is to mark the char field with @XmlTransient, and then write getters and setters which get and set the value as a String:

   @XmlTransient
   char gender = 'M';

   @XmlElement(name="gender")
   public void setGenderAsString(String gender) {
      this.gender = gender.charAt(0);
   }

   public String getGenderAsString() {
      return String.valueOf(gender);
   }

Not very nice, I'll grant you, but short of actually changing your char field tobe a String, that's all I have.

skaffman
This issue is related specifically to the Metro implementation of JAXB, other implementations of JAXB (EclipseLink MOXy) handle this use case correctly.
Blaise Doughan
A: 

This still appears to be a problem in Metro JAXB (the RI), atleast the version of Metro shipped with JDK 1.6.0_20.

EclipseLink JAXB (MOXy) marshals char correctly:

To use EclipseLink JAXB simply add eclipselink.jar to your classpath and add a jaxb.properties file in with your model classes with the following entry:

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
Blaise Doughan
A: 

create a specialized XmlAdapter:

package br.com.maritima.util;

import javax.xml.bind.annotation.adapters.XmlAdapter;

public class CharAdapter extends XmlAdapter<String,Character>{

 @Override
 public String marshal(Character v) throws Exception {
  return new String(new char[]{v});
 }

 @Override
 public Character unmarshal(String v) throws Exception {
   if(v.length()>0)
   return v.charAt(0);
  else return ' ';
 }

}

then you can register it to entire package with package-info.java (avoid to forgot it inside some other class) or use it specifically for a certain field.

see http://blogs.sun.com/CoreJavaTechTips/entry/exchanging_data_with_xml_and for more info.