【问题标题】:Java JSON ProcessingJava JSON 处理
【发布时间】:2018-06-22 14:01:06
【问题描述】:

我很难用 Java 处理下面的 JSON,它是从外部 Ansible 剧本返回的:

{"Sample":
    {
        "tag_description":"abc","tag_category_id":"def","tag_id":"ghi"
    },
    "Sample1":
    {
        "tag_description":"jkl","tag_category_id":"mno","tag_id":"pqr"
    }
 }

我已经能够使用自定义反序列化器成功解析 JSON 的一部分,尽管它只获取第一部分。非常感谢任何想法。

@JsonComponent
public class TagSerializer extends JsonDeserializer<Tag> {



@Override
public Tag deserialize(JsonParser jsonParser,
                        DeserializationContext deserializationContext) throws IOException,
        JsonProcessingException {

    ObjectMapper mapper = new ObjectMapper();
    JsonFactory factory = mapper.getFactory();
    JsonNode treeNode = jsonParser.getCodec().readTree(jsonParser);

    Iterator<Map.Entry<String, JsonNode>> fields = treeNode.fields();
    String name = "";

    // collect the tag name
    Map.Entry<String, JsonNode> entry = fields.next();
    name = entry.getKey();

    // now that we have the tag name, parse it as a separate JSON object
    JsonNode node = entry.getValue();

    // get the values from the JSON
    String description = node.get("tag_description").asText();
    String category_id = node.get("tag_category_id").asText();
    String tag_id = node.get("tag_id").asText();

     return new Tag(name, category_id, description, tag_id);
}

}

我从 Spring Boot REST API 端点调用该方法,我的“标签”模型是一个 Spring 实体:

“标签”模型:

@Entity
@JsonDeserialize(using = TagSerializer.class)
public class Tag {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;

private String name;
private String tag_category_id;
private String tag_description;
private String tag_id;

//JPA requires that a default constructor exists
//for entities
protected Tag() {}

public Tag(String name,
           String tag_category_id,
           String tag_description,
           String tag_id) {
    this.name = name;
    this.tag_category_id = tag_category_id;
    this.tag_description = tag_description;
    this.tag_id = tag_id;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public String getTag_category_id() {
    return tag_category_id;
}

public void setTag_category_id(String tag_category_id) {
    this.tag_category_id = tag_category_id;
}

public String getTag_description() {
    return tag_description;
}

public void setTag_description(String tag_description) {
    this.tag_description = tag_description;
}

public String getTag_id() {
    return tag_id;
}

public void setTag_id(String tag_id) {
    this.tag_id = tag_id;
}

public String toString() {

    return "<Tag:[Name: " + this.name + "],[tag_category: "+
            this.tag_category_id + "],[tag_description: "+
            this.tag_description + "],[tag_id:"+this.tag_id+"]";

}
}

Spring Boot 端点:

@PostMapping(value="/store", consumes = APPLICATION_JSON_VALUE)
public void tagJson(@RequestBody String json) {
    // delete any existing tags
    tagRepository.deleteAll();

    //lets modify the json to make it look nicer
    String modjson = "["+json+"]";

    ObjectMapper mapper = new ObjectMapper();
    try {
        Tag[] tags = mapper.readValue(modjson, Tag[].class);
        for (Tag t : tags)
            tagRepository.save(t);
    } catch (Exception exception) {
        exception.printStackTrace();
    }
}

【问题讨论】:

    标签: java json spring jackson


    【解决方案1】:

    如果您使用 Spring MVC,请考虑在引用 @RequestBody 时明确声明所需的类型,并让框架为您完成这项工作

    @PostMapping(value="/store", consumes = APPLICATION_JSON_VALUE)
    public void tagJson(@RequestBody Map<String, Tag> json) {
      // Do not mess with ObjectMapper here, Spring will do the thing for you
    }
    

    【讨论】:

    • 太棒了,效果很好!使用它,我可以简单地设置标签上返回的字符串名称,并保存到 JPA 存储库中。谢谢大家!
    【解决方案2】:

    这不是直接的答案,而是使用 Gson 的可能方向的指南。

    package test;
    import java.util.Map;
    import com.google.gson.Gson;
    public class JsonTest {
        public static void main(final String... args) {
            new JsonTest().run();
        }
        public void run() {
            final Gson gson = new Gson();
            final Map<?, ?> result = gson.fromJson("{" + 
                    "    \"Sample\": {" + 
                    "        \"tag_description\": \"abc\"," + 
                    "        \"tag_category_id\": \"def\"," + 
                    "        \"tag_id\": \"ghi\"" + 
                    "    }," + 
                    "    \"Sample1\": {" + 
                    "        \"tag_description\": \"jkl\"," + 
                    "        \"tag_category_id\": \"mno\"," + 
                    "        \"tag_id\": \"pqr\"" + 
                    "    }" + 
                    "}", Map.class);
            System.out.println("Map size: " + result.size());
        }
    }
    

    结果大小为 2。映射条目是键值 Sample、Sample1,值是包含节点的列表。您可以使用调试器看到这一点。

    【讨论】:

    • 非常感谢您的回复! Spring 框架最终承担了很多繁重的工作,但我肯定会看看 Gson
    • Spring 集成了 Jackson JSON 处理器,它与 Gson 相当。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-13
    • 1970-01-01
    • 1970-01-01
    • 2019-02-28
    • 2012-04-29
    相关资源
    最近更新 更多