java 如何将具有各种数据类型的输入存储到单个变量中(String,Int,Date,List)

a1o7rhls  于 2023-04-04  发布在  Java
关注(0)|答案(3)|浏览(147)

在UI中,我需要支持选择条件,并根据条件必须提供输入。输入可以是下面列出的其中一个:

  • 数量
  • 日期
  • 金额
  • LIST - [“Option 1”,“Option 2”] -多选
  • 范围-(最小值和最大值)

一旦被选中,它将被填充为JSON。
Java类看起来像下面的字段及其getter和setter:

private String condition;
private String value;
private List<String> valueList;
private String valueType;
private int minValue;
private int maxValue;

金额如下:

{
  "condition": "Basket Value",
  "value": "5",
  "dataType": "AMOUNT",
}

对于范围,如下所示:

{
  "condition": "Percentile",
  "dataType": "RANGE",
  "minValue": 10,
  "maxValue": 60
}

对于LIST,如下所示:

{
  "condition": "Options",
  "dataType": "LIST",
  "valueList": ["option1", "option2"]
}

而不是有valuevalueListattributeMinattributeMax。我如何将其存储在一个变量中?
使用Object是最好的解决方案吗?还有其他解决方案吗?我不能在Java中使用var来解决这个问题。

Object inputValue;

数据将保存到MongoDB。

aurhwmvo

aurhwmvo1#

你可以通过多态序列化和反序列化来实现这一点。这个例子使用了记录和密封类型,但是在重写为不使用密封类型和使用“普通”POJO时也应该可以工作。
我使用Jackson(com.fasterxml.jackson.core:jackson-databind:2.14.2)来实现这一点,并使用@JsonSubTypes注解来声明从dataType属性到相应类的Map。我只列出了问题中的示例,但对QUANTITY和DATE这样做应该遵循这一点。
将接口定义为类型的根:

import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "dataType")
@JsonSubTypes({
        @JsonSubTypes.Type(value = AmountValue.class, name = "AMOUNT"),
        @JsonSubTypes.Type(value = RangeValue.class, name = "RANGE"),
        @JsonSubTypes.Type(value = ListValue.class, name = "LIST"),
})
public sealed interface Condition 
        permits AmountValue, 
                ListValue, 
                RangeValue {

    String condition();

}

以及每种类型的单个记录:
x一个一个一个一个x一个一个二个一个x一个一个三个一个
序列化和反序列化示例:

public class Example {

    public static void main(String[] args) throws JsonProcessingException {
        var conditionHolder = new ConditionHolder(
                new AmountValue("Basket Value", "5"),
                new RangeValue("Percentile", 10, 60),
                new ListValue("Percentile", List.of("option1", "option2")));

        var mapper = new ObjectMapper()
                .configure(SerializationFeature.INDENT_OUTPUT, true);

        System.out.println("serialized format");
        System.out.println(mapper.writeValueAsString(conditionHolder));
        System.out.println("===============================");
        System.out.println("deserialized result");

        ConditionHolder deserialized = mapper.readValue("""
                {
                  "conditionList" : [ {
                    "dataType" : "AMOUNT",
                    "condition" : "Basket Value",
                    "value" : "5"
                  }, {
                    "dataType" : "RANGE",
                    "condition" : "Percentile",
                    "minValue" : 10,
                    "maxValue" : 60
                  }, {
                    "dataType" : "LIST",
                    "condition" : "Percentile",
                    "valueList" : [ "option1", "option2" ]
                  } ]
                }
                """, ConditionHolder.class);
        System.out.println(deserialized);
    }

    public record ConditionHolder(List<Condition> conditionList) {

        public ConditionHolder {
            conditionList = List.copyOf(conditionList);
        }

        public ConditionHolder(Condition... conditions) {
            this(List.of(conditions));
        }

    }

}

输出(为了可读性,在反序列化结果中添加了换行符):

serialized format
{
  "conditionList" : [ {
    "dataType" : "AMOUNT",
    "condition" : "Basket Value",
    "value" : "5"
  }, {
    "dataType" : "RANGE",
    "condition" : "Percentile",
    "minValue" : 10,
    "maxValue" : 60
  }, {
    "dataType" : "LIST",
    "condition" : "Percentile",
    "valueList" : [ "option1", "option2" ]
  } ]
}
===============================
deserialized result
ConditionHolder[conditionList=[
  AmountValue[condition=Basket Value, value=5], 
  RangeValue[condition=Percentile, minValue=10, maxValue=60],
  ListValue[condition=Percentile, valueList=[option1, option2]]
]]

显然,要在代码中实际使用这些类型和它们的值,必须进行instanceof检查,但是一旦模式匹配switch着陆(可能在Java 21中),这种类型的处理可以进一步简化。或者,也可以通过Condition中的方法定义必要的求值或行为,但是否可能取决于您试图解决的问题。
如果需要“手动”执行序列化或反序列化(例如,因为您使用的库不支持多态序列化/反序列化),那么您需要模仿Jackson的做法。(dataType),然后是实际对象的属性。对于反序列化,使用 discriminator 属性(dataType)来决定要创建的类型,并从JSON对象中读取该类型的属性。

nc1teljy

nc1teljy2#

乍一看,我可以看到您可以使用HashMap变量。

HashMap<String, Object> data = new HashMap<String, Object>();

现在你可以输入任何类型的数据而不会有任何问题。确保你对空值使用了正确的验证。希望这对你有帮助。

ukxgm1gy

ukxgm1gy3#

虽然我不确定为什么你只想使用单个变量,但你可以将数据存储在单个STRING中,并用逗号分隔多个参数。

{
     "condition": "Basket Value",
     "dataType": "AMOUNT",
     "inputValue": "5"
     
}

{
    "condition": "Percentile",
    "dataType": "RANGE",
    "inputValue": "10,60"
}

{
    "condition": "Percentile",
    "dataType": "RANGE",
    "inputValue": "option1, option2"
}

相关问题