Java 如何将逗号分隔的字符串反序列化为列表?
我有一个类似的json:Java 如何将逗号分隔的字符串反序列化为列表?,java,list,jackson,Java,List,Jackson,我有一个类似的json: { "names": "John, Tom", "values": "8, 9", "statuses": "yes, no" } 并希望反序列化为: class Bean { private List<String> names; private List<Integer> values; priva
{
"names": "John, Tom",
"values": "8, 9",
"statuses": "yes, no"
}
并希望反序列化为:
class Bean {
private List<String> names;
private List<Integer> values;
private List<StatusEnum> statuses;
}
我不知道如何将字符串反序列化为已知的内容类型。有什么方法可以实现通用反序列化器吗?您的Bean不能正确地表示JSON。正确的版本应该如下所示
class Bean {
private String names;
private Integer values;
private String statuses;
}
你可以用
最后,您可以将Bean对象分解为名称、值和状态列表,以供进一步使用。为了避免手动反序列化和处理所有可能的类型,我们可以使用这样一个事实,即列表中的所有项在使用引号(
“
)字符包装时也是JSON
元素
因此,我们可以将John,Tom
转换为“John”,“Tom”
,8,9
转换为“8”,“9”
等等
我们可以使用默认的Jackson
行为,该行为允许处理意外的令牌。在我们的例子中,当需要JSON数组时,STRING
令牌出现。要处理这些情况,我们可以使用com.fasterxml.Jackson.databind.deser.DeserializationProblemHandler
类。它可以如下所示:
class ComaSeparatedValuesDeserializationProblemHandler extends DeserializationProblemHandler {
@Override
public Object handleUnexpectedToken(DeserializationContext ctxt, JavaType targetType, JsonToken token, JsonParser parser, String failureMsg) throws IOException {
if (token == JsonToken.VALUE_STRING && targetType.isCollectionLikeType()) {
return deserializeAsList(targetType, parser);
}
return super.handleUnexpectedToken(ctxt, targetType, token, parser, failureMsg);
}
private Object deserializeAsList(JavaType listType, JsonParser parser) throws IOException {
String[] values = readValues(parser);
ObjectMapper mapper = (ObjectMapper) parser.getCodec();
JavaType itemType = listType.getContentType();
List<Object> result = new ArrayList<>();
for (String value : values) {
result.add(convertToItemType(mapper, itemType, value));
}
return result;
}
private Object convertToItemType(ObjectMapper mapper, JavaType contentType, String value) throws IOException {
final String json = "\"" + value.trim() + "\"";
return mapper.readValue(json, contentType);
}
private String[] readValues(JsonParser p) throws IOException {
final String text = p.getText();
return text.split(",");
}
}
我使用和库只是为了使它变得简单和简短,但它们不是使它工作的必需条件。您所说的“许多其他内容类型,包括自定义类型”是什么意思“。您使用的是JSON,所以内容类型不会是application/JSON
?您可以控制JSON吗?也就是说,你能从根本上解决这个问题,并让你的JSON准确地反映数据模型吗?嗨,我想知道答案出了什么问题,如果模型可以更改,它将解决问题(正如@dnault所评论的)。但如果模型无法更改,请忽略我的回答。谢谢
ObjectMapper objectMapper = new ObjectMapper();
Bean bean = objectMapper.readValue(json, Bean.class);
class ComaSeparatedValuesDeserializationProblemHandler extends DeserializationProblemHandler {
@Override
public Object handleUnexpectedToken(DeserializationContext ctxt, JavaType targetType, JsonToken token, JsonParser parser, String failureMsg) throws IOException {
if (token == JsonToken.VALUE_STRING && targetType.isCollectionLikeType()) {
return deserializeAsList(targetType, parser);
}
return super.handleUnexpectedToken(ctxt, targetType, token, parser, failureMsg);
}
private Object deserializeAsList(JavaType listType, JsonParser parser) throws IOException {
String[] values = readValues(parser);
ObjectMapper mapper = (ObjectMapper) parser.getCodec();
JavaType itemType = listType.getContentType();
List<Object> result = new ArrayList<>();
for (String value : values) {
result.add(convertToItemType(mapper, itemType, value));
}
return result;
}
private Object convertToItemType(ObjectMapper mapper, JavaType contentType, String value) throws IOException {
final String json = "\"" + value.trim() + "\"";
return mapper.readValue(json, contentType);
}
private String[] readValues(JsonParser p) throws IOException {
final String text = p.getText();
return text.split(",");
}
}
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.deser.DeserializationProblemHandler;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.google.common.base.Joiner;
import lombok.Data;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class ConvertStringToCollectionApp {
public static void main(String[] args) throws IOException {
File jsonFile = new File("./resource/test.json").getAbsoluteFile();
ObjectMapper mapper = JsonMapper.builder()
.addHandler(new ComaSeparatedValuesDeserializationProblemHandler())
.build();
Bean bean = mapper.readValue(jsonFile, Bean.class);
print(bean.getNames());
print(bean.getValues());
print(bean.getStatuses());
}
private static void print(List<?> values) {
values.stream().findFirst().ifPresent(value -> System.out.print(value.getClass().getSimpleName() + "s: "));
System.out.println(Joiner.on(", ").join(values));
}
}
@Data
class Bean {
private List<String> names;
private List<Integer> values;
private List<StatusEnum> statuses;
}
enum StatusEnum {
yes, no
}
Strings: John, Tom
Integers: 8, 9
StatusEnums: yes, no