在Spring MVC GET请求中将Json属性名称转换为实体属性名称

问题描述:

嗨我有一个应用程序正在使用SpringDataNeo4j,Spring MVC ... 我有以下类作为示例。一个是实体,另一个是JSON对象。在Spring MVC GET请求中将Json属性名称转换为实体属性名称

@NodeEntity(label="MyBean") 
public class MyBean() { 

    @Property(name = "my_name") 
    String my_name; 
    @Property(name = "last_modified_by") 
    String last_modified_by; 

    //setter & getters 
} 

@JsonRootName("myBean") 
@JsonInclude(JsonInclude.Include.NON_EMPTY) 
public class MyBeanData { 

    String myName; 
    String lastModifiedBy; 

    //setter getters 
} 

这是我的Spring MVC控制器的请求处理程序:

@RequestMapping(value = "/test", method = RequestMethod.GET) 
public List<MyBeanData> getMyBeans(@RequestParam(name = "sortDir", required = false) String sortDir, 
     @RequestParam(name = "sortProp", required = false) String sortProp){ 

    //execute the Custom query to get all mybeans sorted by sortProp 
} 

现在我的问题是,在“sortProp”所用的属性名称是JSON对象属性的名称,例如“lastModifiedBy”。 ..排序查询不适用于json属性名称,只有在使用实体属性名称时才起作用。在执行查询之前,是否有简单的&干净的方式将单个json属性NAME转换为对应的实体属性NAME?我不想在下面的转换器方法中添加如此多的实体。

public String converter(String sortProp){ 
    if("lastModifiedBy".equals(sortPro)){ 
     return "last_modified_by" 
    } 
} 

首先,你并不需要使用很多,如果/别人的,即使你要反复比较字符串,就可以对字符串进行切换:

switch (sortPro) { 
    case "lastModifiedBy": return "last_modified_by"; 
    // ... 
} 

然而,最简单的方法存储映射和执行转换是使用Map<String, String>

private static final Map<String, String> SORT_FIELD_MAP; 

static { 
    Map<String, String> sortFieldMap = new HashMap<>(); 
    sortFieldMap.put("lastModifiedBy", "last_modified_by"); 
    // ... 
    SORT_FIELD_MAP = Collections.unmodifiableMap(sortFieldMap); 
} 

public String converter(String sortProp) { 
    return SORT_FIELD_MAP.get(sortProp); 
} 

(获自Guava或等效或者使用不可改变的集合)

+0

有什么办法可以用这个杰克逊呢?只是好奇......我已经有了实体和JSON对象..所以我想也许我们已经实现了一个解决方案。我有这么多的班级,所以我不想完成所有的课程并添加转换器... – Lina

+0

我不明白,杰克逊不关心将DTO映射到实体。然而,您可以使用自己的一套注释开发自己的解决方案来注册映射:注释DTO的字段,使用转换服务注册这些类,转换服务将反省它们并存储每个类的映射(映射图) ,然后只需使用类和排序属性的名称来调用服务。我不知道已经有这样做的解决方案。 –

+0

谢谢@Frank。我将使用您建议的实现 – Lina

我发布这个答案只是弗兰克建议的替代实现。

因此,这里是我做的步骤: 使用Reflection library在这里,我创建了一个地图,其中的:

  • 关键是 - >使用@Property注释的所有字段的名称
  • 价值是 - >所有属性的属性值

BeanPackage是我们要扫描的类的包路径。

@PostConstruct 
private void init() { 
    List<ClassLoader> classLoadersList = new LinkedList<ClassLoader>(); 
    classLoadersList.add(ClasspathHelper.contextClassLoader()); 
    classLoadersList.add(ClasspathHelper.staticClassLoader()); 

    Reflections reflections = new Reflections(new ConfigurationBuilder() 
      .setScanners(
        new SubTypesScanner(false /* don't exclude Object.class */), 
        new ResourcesScanner(), 
        new FieldAnnotationsScanner()) 
      .setUrls(ClasspathHelper.forClassLoader(classLoadersList.toArray(new ClassLoader[0]))) 
      .filterInputsBy(new FilterBuilder().include(FilterBuilder.prefix(beanPackage)))); 

    Set<Field> fields = reflections.getFieldsAnnotatedWith(Property.class); 
    fields.forEach(field -> jsonToEntityMap.put(field.getName(), field.getAnnotation(Property.class).name())); 
+1

由于您有一个'Map ',请确保您没有类之间的冲突。否则,可以使用Map >,Map ,String>或Guava'Table 。 –

+0

我没有碰撞,属性名称始终是由'_'版本的json属性分隔的降低的情况。所以即使在重复的情况下,他们也会有正确的映射。但是,如果发生碰撞,您的选择就是解决方案。 – Lina