2014-11-04 10 views
5

Wenn ich ein Objekt serialisieren/deserialisieren, werden alle Feldnamen in Kleinbuchstaben konvertiert. Gibt es irgendeine Konfiguration, die Jackson dazu bringt, die Feldnamen genau so zu behalten, wie sie sind? Sowohl zum Serialisieren als auch zum Deserialisieren?Jackson ObjectMapper Groß-/Kleinschreibungsprobleme

(Ich weiß, über @JsonProperty, aber dies scheint nicht richtig zu sein, da ich brauche, was gerade für Jackson zu respektieren, was bereits vorhanden ist)

Mein Testcode:

import java.io.Serializable; 

import com.fasterxml.jackson.databind.DeserializationFeature; 
import com.fasterxml.jackson.databind.ObjectMapper; 
import com.fasterxml.jackson.databind.PropertyNamingStrategy; 
import com.fasterxml.jackson.databind.SerializationFeature; 
import com.fasterxml.jackson.databind.cfg.MapperConfig; 
import com.fasterxml.jackson.databind.introspect.AnnotatedField; 
import com.fasterxml.jackson.databind.introspect.AnnotatedMethod; 

public class Test { 

    static class Example implements Serializable { 
     private String Test; 
     private String ABC; 
     private String XyZ; 

     public String getTest() { return Test; } 
     public void setTest(String test) { Test = test; } 

     public String getABC() { return ABC; } 
     public void setABC(String abc) { ABC = abc; } 

     public String getXyZ() { return XyZ; } 
     public void setXyZ(String xyz) { XyZ = xyz; } 
    } 

    static class MyPropertyNamingStrategy extends PropertyNamingStrategy { 
     @Override 
     public String nameForField(MapperConfig<?> config, AnnotatedField field, String defaultName) { 
      return convert(defaultName); 
     } 
     @Override 
     public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) { 
      return convert(defaultName); 
     } 
     @Override 
     public String nameForSetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) { 
      return convert(defaultName); 
     } 
     private String convert(String input) { 
      return input; 
     } 
    } 

    public static void main(String[] args) throws Exception { 
     ObjectMapper objectMapper = new ObjectMapper() 
     .setPropertyNamingStrategy(new MyPropertyNamingStrategy()) 
     .enable(SerializationFeature.INDENT_OUTPUT) 
     .configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);  

     //From OBJECT to JSON 
     Example ex = new Example(); 
     ex.setTest("1"); 
     ex.setABC("2"); 
     ex.setXyZ("3"); 
     System.out.println(objectMapper.writeValueAsString(ex)); 

     //FROM JSON to OBJECT 
     String jsonString = "{ \"Test\":\"0\", \"ABC\":\"1\", \"XyZ\":\"2\" }"; 
     Example fEx = objectMapper.readValue(jsonString, Example.class); 
    } 

} 

Dank @ BlueLettuce16, ich habe es geschafft, eine "verbesserte" Version des PropertyNamingStrategy zu bauen. Hier ist sie:

import java.lang.reflect.Modifier; 

import com.fasterxml.jackson.databind.PropertyNamingStrategy; 
import com.fasterxml.jackson.databind.cfg.MapperConfig; 
import com.fasterxml.jackson.databind.introspect.AnnotatedField; 
import com.fasterxml.jackson.databind.introspect.AnnotatedMethod; 

public class CustomPropertyNamingStrategy extends PropertyNamingStrategy { 

    @Override 
    public String nameForField(MapperConfig<?> config, AnnotatedField field, String defaultName) { 
     return convertForField(defaultName); 
    } 

    @Override 
    public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) { 
     return convertForMethod(method, defaultName); 
    } 

    @Override 
    public String nameForSetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) { 
     return convertForMethod(method, defaultName); 
    } 

    private String convertForField(String defaultName) { 
     return defaultName; 
    } 

    private String convertForMethod(AnnotatedMethod method, String defaultName) { 
     if (isGetter(method)) { 
      return method.getName().substring(3); 
     } 
     if (isSetter(method)) { 
      return method.getName().substring(3); 
     } 
     return defaultName; 
    } 

    private boolean isGetter(AnnotatedMethod method) { 
     if (Modifier.isPublic(method.getModifiers()) && method.getGenericParameterTypes().length == 0) { 
      if (method.getName().matches("^get[A-Z].*") && !method.getGenericReturnType().equals(void.class)) 
       return true; 
      if (method.getName().matches("^is[A-Z].*") && method.getGenericReturnType().equals(boolean.class)) 
       return true; 
     } 
     return false; 
    } 

    private boolean isSetter(AnnotatedMethod method) { 
     return Modifier.isPublic(method.getModifiers()) && method.getGenericReturnType().equals(void.class) && method.getGenericParameterTypes().length == 1 
       && method.getName().matches("^set[A-Z].*"); 
    } 

} 
+3

implementiert eine benutzerdefinierte [ 'PropertyNamingStrategy'] (https://github.com/FasterXML/jackson-databind/ blob/master/src/main/java/com/schneller xml/jackson/databind/PropertyNamingStrategy.java), vielleicht –

+0

Wie verwenden Sie @ JsonProperty? Übergeben Sie es den String-Feldnamen? –

+0

Ich sehe keine Möglichkeit, das PropertyNamingStrategy so zu implementieren, dass die Feldnamen korrekt übereinstimmen. Wenn ein Feld den Namen "ABC" hat, wird ein anderes mit XYz benannt, die beim Serialisieren/Deserialisieren NICHT mit dem JSON übereinstimmen. – MBarni

Antwort

2

Ich denke, dass dies die Lösung (unter Verwendung von benutzerdefinierten PropertyNamingStrategy):

import com.fasterxml.jackson.databind.PropertyNamingStrategy; 
import com.fasterxml.jackson.databind.cfg.MapperConfig; 
import com.fasterxml.jackson.databind.introspect.AnnotatedField; 
import com.fasterxml.jackson.databind.introspect.AnnotatedMethod; 

public class MyPropertyNamingStrategy extends PropertyNamingStrategy { 
    @Override 
    public String nameForField(MapperConfig<?> config, AnnotatedField field, String defaultName) { 
     return convert(field.getName()); 
    } 

    @Override 
    public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) { 
     return convert(method.getName().toString()); 
    } 

    @Override 
    public String nameForSetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) { 
     return convert(method.getName().toString()); 
    } 

    private String convert(String input) { 
     return input.substring(3); 
    } 
} 

-Test

import com.fasterxml.jackson.databind.ObjectMapper; 
import com.fasterxml.jackson.databind.SerializationFeature; 

import java.io.IOException; 
import java.io.StringWriter; 

public class MyPropertyNamingStrategyTest { 
    public static void main(String[] args) { 
     PrivatePerson privatePerson = new PrivatePerson(); 
     privatePerson.setFirstName("John"); 
     privatePerson.setLastName("Smith"); 

     ObjectMapper mapper = new ObjectMapper(); 
     mapper.setPropertyNamingStrategy(new MyPropertyNamingStrategy()); 
     mapper.enable(SerializationFeature.INDENT_OUTPUT); 
     StringWriter sw = new StringWriter(); 
     try { 
      mapper.writeValue(sw, privatePerson); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     System.out.println(sw.toString()); 
    } 
} 

PrivatePerson

public class PrivatePerson { 
    private String firstName; 
    private String lastName; 

    public void setFirstName(String firstName) { 
     this.firstName = firstName; 
    } 

    public String getFirstName() { 
     return firstName; 
    } 

    public void setLastName(String lastName) { 
     this.lastName = lastName; 
    } 

    public String getLastName() { 
     return lastName; 
    } 
} 
+0

Jetzt sind die Felder alle in Großbuchstaben. Serialisierung und Deserialisierung funktioniert nur, wenn die Klassenfelder alle in Großbuchstaben sind. – MBarni

+0

Haben Sie versucht, die Konvertierungsmethode zu ändern, um die Eingabe zurückzugeben? private String konvertieren (String-Eingabe) { Return-Eingang; } – BlueLettuce16

+0

Ja, tat ich. Der Unterschied ist, dass sie jetzt alle in der unteren Reihe sind. Der Fall wird nie respektiert, oder sie sind alle Upper, alle Lower, oder Pascal (erster Buchstabe in der Oberschale) ... Aber NUR die Antwort auf den Fall ist keine Option gefunden. – MBarni

5

Ich habe hatte das gleiche Problem.

Dies ist meine Lösung:

public class MyNamingStrategy extends PropertyNamingStrategy { 

    @Override 
    public String nameForField(MapperConfig<?> config, AnnotatedField field, String defaultName) { 
     return field.getName(); 
    } 

    @Override 
    public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) { 
     return convert(method, defaultName); 
    } 

    @Override 
    public String nameForSetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) { 
     return convert(method, defaultName); 
    } 

    private String convert(AnnotatedMethod method, String defaultName) { 

     Class<?> clazz = method.getDeclaringClass(); 
     List<Field> flds = FieldUtils.getAllFieldsList(clazz); 
     for (Field fld : flds) { 
      if (fld.getName().equalsIgnoreCase(defaultName)) { 
       return fld.getName(); 
      } 
     } 

     return defaultName; 
    } 
} 

In diesem Fall werden Sie den genauen Namen der Eigenschaft erhalten, und wird nicht auf den korrekten Namen der Methoden abhängen müssen.

1

Sie können Jackson konfigurieren Groß- und Kleinschreibung, tolerant zu sein:

ObjectMapper mapper = new ObjectMapper(); 
mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true); 

Cudos zu https://stackoverflow.com/a/32842962/1639556

+0

wird das für die Serialisierung oder einfach für die Deserialisierung helfen? – eis

+0

Ich habe dies für die Deserialisierung eingehender Anfrage versucht. Aber es macht für mich keinen Sinn, dass es die Serialisierung beeinträchtigen würde. Sie haben das Objekt bereits und es muss jedes Mal nur auf eine bestimmte Art serialisiert werden. –

+0

In der Tat, so löst es nicht das Problem, das OP hat - er möchte die ursprünglichen Versionen sowohl für das Serialisieren als auch das Deserialisieren haben. – eis

Verwandte Themen