【问题标题】:Map JSON string or JSON array to String in Java object [duplicate]将JSON字符串或JSON数组映射到Java对象中的字符串[重复]
【发布时间】:2021-09-27 15:51:27
【问题描述】:

我有一个由 Elixir 类创建的 JSON,它有一个可以是字符串或数组的字段:

field :logs, {:array, :string}

如果有人不明白这一点,那就是

{"logs" : "some log 1"}

{
"logs": ["some log 1", "some log 2"]
}

我为此映射了一个 Java 字段:

@JsonProperty("logs")
private String logs;

此映射仅在 logsString 出现时有效,但如果 logsarray 出现时失败,并显示无法将 START_ARRAY 转换为 string 的错误。

如果字段是数组,如何序列化并存储为逗号分隔的字符串?

【问题讨论】:

  • 使用Object,然后使用instanceof检查实际类型?

标签: java json jackson jettison


【解决方案1】:

我在标签中看到您使用 Jackson 进行解析。这意味着您需要为您的 logs 字段编写自定义反序列化器并向 Jackson 注册。

这种解决方案的一个例子:

package tmp;

import java.io.IOException;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.exc.MismatchedInputException;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ValueNode;

public class JacksonDemo {

    public static class LogHolder {
        @JsonProperty("logs")
        @JsonDeserialize(using = ArrayOrStringJsonDeserializer.class)
        private String logs;

        @Override
        public String toString() {
            return "LogHolder(logs=" + logs + ")";
        }
    }

    public static class ArrayOrStringJsonDeserializer extends JsonDeserializer<String> {

        @Override
        public String deserialize(JsonParser jsonParser, DeserializationContext ctxt) throws IOException, JsonProcessingException {
            JsonNode node = (JsonNode) jsonParser.readValueAsTree();
            if (node.isValueNode()) {
                ValueNode valueNode = (ValueNode) node;
                if (valueNode.isTextual()) {
                    return valueNode.textValue();
                }
            } else if (node.isArray()) {
                ArrayNode arrayNode = (ArrayNode) node;
                return StreamSupport.stream(Spliterators.spliteratorUnknownSize(arrayNode.iterator(), Spliterator.ORDERED), false)
                        .map(JsonNode::textValue)
                        .collect(Collectors.joining(", "));
            }
            throw MismatchedInputException.from(jsonParser, String.class,
                    "Expected node to be of type String or array, but got " + node.getNodeType().toString());
        }

    }

    public static void main(String args[]) throws Exception {
        String[] docs = { "{\"logs\" : \"some log 1\"}", "{\"logs\": [\"some log 1\", \"some log 2\"]}" };

        ObjectMapper om = new ObjectMapper();
        for (String doc : docs) {
            System.out.println(om.readValue(doc, LogHolder.class));
        }
    }
}

执行此代码的结果:

LogHolder(logs=some log 1)
LogHolder(logs=some log 1, some log 2)

【讨论】:

  • P.S.注意我在这里对类型检查有点严格——明确地只允许 String 和 Array JSON 类型,并且只从数组中获取文本值(所有其他类型都将返回 null)。但是 - 如果需要 - 很容易让它更“放松”并允许数字等。
猜你喜欢
  • 2018-05-29
  • 2019-07-18
  • 2018-01-12
  • 1970-01-01
  • 2020-10-09
  • 2016-05-31
  • 1970-01-01
  • 2019-01-25
  • 2018-02-10
相关资源
最近更新 更多