Spring Boot Rest API枚举一些Java类型

huangapple go评论71阅读模式
英文:

Spring Boot Rest API Enumerate some Java types

问题

我正在构建Spring Boot Webflux REST API功能,需要处理包含几种Java类型(例如String、Integer、Double)信息的数据,作为JSON请求/响应的一部分。表示Java类型的属性还必须在mongodb中可持久化存储(一旦JSON可以处理这种属性,就不应该有问题)。我有以下的模型类和类型枚举,REST API使用它们来序列化/反序列化JSON消息。

@Getter
@ToString
@EqualsAndHashCode(exclude = "id")
@Document(collection = "core_scheme")
@JsonDeserialize(builder = SchemeModel.Builder.class)
@Builder(builderClassName = "Builder", toBuilder = true, setterPrefix = "with")
public class SchemeModel {

    @Id
    private final String id;

    @Field(name = "userId") private final String userId;
    @Field(name = "date") private final String creationDate;
    @Field(name = "properties") private final Map<String, SchemeTypes> properties;
}
public enum SchemeTypes {
    INTEGER, STRING, DOUBLE
}

序列化和反序列化工作正常。现在的问题是,当我想解析存储在 Map<String, SchemeTypes> properties 映射内的真实Java类型时,我需要进行类似于以下的映射(只是抽象,不是真实代码):

SchemeTypes.INTEGER => Java Integer类  
SchemeTypes.STRING => Java String类  
SchemeTypes.DOUBLE => Java Double类  

有没有更简单的方法来表示存储在模型类内部并在序列化/反序列化的JSON文件中使用的Java类型,以便我可以直接用它来推断Java类型,而无需额外验证它是否是有效的Java类型。例如,如果在上述枚举中列出的类型与真实的Java类型具有完全相同的命名,我可以按照以下方式做,而无需进行任何映射:

public void deduceClass(SchemeTypes type) {
    Class myClass = Class.forName(type.toString());
}

请注意,我正在寻找一个可以开箱即用的解决方案(我不必验证用户提供的类型)。如果这种解决方案比上述的映射更难以实现,我将坚持使用映射。

英文:

I am building Spring Boot webflux REST API functionality that needs to work with data containing few Java type's (let's consider String, Integer, Double for example) information as part of JSON request/responses. Attribute representing Java type must be persistable inside mongodb as well (should not be problem once JSON can work with such attribute). I have following model class and type enumeration which is used by REST API to serialize/deserialize JSON message's.

@Getter
@ToString
@EqualsAndHashCode(exclude = &quot;id&quot;)
@Document(collection = &quot;core_scheme&quot;)
@JsonDeserialize(builder = SchemeModel.Builder.class)
@Builder(builderClassName = &quot;Builder&quot;, toBuilder = true, setterPrefix = &quot;with&quot;)
public class SchemeModel {

    @Id
    private final String id;

    @Field(name = &quot;userId&quot;) private final String userId;
    @Field(name = &quot;date&quot;) private final String creationDate;
    @Field(name = &quot;properties&quot;) private final Map&lt;String, SchemeTypes&gt; properties;
}
public enum SchemeTypes {
    INTEGER, STRING, DOUBLE
}

Serialization and deserialization work's well. Now the problem is that when i want to resolve real Java type's stored inside Map&lt;String, SchemeTypes&gt; properties map i need to do mapping similar to this (just abstraction not real code):

SchemeTypes.INTEGER =&gt; Java Integer class  
SchemeTypes.STRING =&gt; Java String class  
SchemeTypes.DOUBLE =&gt; Java Double class  

Is there any more simple way to represent Java type's stored inside model class and used within serialized/deserialized JSON file's so i can directly use it to deduce Java type without additional validation that it's valid Java type. For example if type's enumarated inside mentioned enum would have exactly same naming as real Java type's i could do following without any mapping:

public void deduceClass(SchemeTypes type) {
    Class myClass = Class.forName(type.toString());
}

Note that i am looking for a solution which would work out of the box (i don't have to validate type's provided by user). If such solution would be harder to implement as mentioned mapping i will stick with mapping.

答案1

得分: 1

如果您不保存此实体,我可以说您实际上可以直接将SchemeTypes映射到相应的类,如下所示:

public enum SchemeTypes {
    INTEGER(Integer.class), STRING(String.class), DOUBLE(Double.class);
   
    private final Class clazz;
    
    private SchemeTypes(Class clazz){
       this.clazz = clazz;
    }
        
    public Class getClazz(){
       return clazz;
    }
}

但是由于您要保存这个实体,这可能会导致一些反序列化问题。
也许您可以不直接保存SchemaType实例,而只保存枚举的名称,以克服这个问题,如下所示:

private final Map<String, String> properties;

并且可以通过此类上的静态方法找到相应的clazz值,如下所示:

public static Class findClazzFor(String schemeTypeName){
    return SchemeTypes.valueOf(schemeTypeName).getClazz();
}

不过,我认为最干净的解决方案是将SchemeType类实例的映射保存在某个地方,作为一对一的映射。然后像上面的getClazz方法中那样,为提供的schemeType检索相应的类。

英文:

If you weren't saving this entity I could say you can actually directly map the SchemeTypes into corresponding class like following

public enum SchemeTypes {
    INTEGER(Integer.class), STRING(String.class), DOUBLE(Double.class);

    private final Class clazz;

    private SchemeTypes(Class clazz){
       this.clazz = clazz;
    }
    
    public Class getClazz(){
       return clazz;
    }
}

But as you are saving this it could cause some issue to deserialize.
Maybe you can save not the SchemaType instance directly but just the name of enum to overcome this like following

private final Map&lt;String, String&gt; properties;

and find the corresponding clazz value with a static method on this class like following

public static Class findClazzFor(String schemeTypeName){
       return SchemeTypes.valueOf(schemeTypeName).getClazz();
    }

Nevertheless I think cleanest solution would be keeping the SchemeType class instance mapping somewhere as a one-to-one map. And retrieve the corresponding class for provided schemeType as in the getClazz method above.

huangapple
  • 本文由 发表于 2020年7月26日 06:46:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/63094336.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定