Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java中JSON格式之间的映射_Java_Json - Fatal编程技术网

Java中JSON格式之间的映射

Java中JSON格式之间的映射,java,json,Java,Json,我将从JavaScript/Ruby开始学习Java。假设我为动物提供了以下JSON对象: { name: { common: "Tiger", latin: "Panthera tigris" } legs: 4 } 我正在处理许多动物API,我想将它们规范化为我自己的通用格式,如: { common_name: "Tiger", latin_name: "Panthera tigris", limbs: { legs: 4, arms

我将从JavaScript/Ruby开始学习Java。假设我为动物提供了以下JSON对象:

{
  name: {
    common: "Tiger",
    latin: "Panthera tigris"
  }
  legs: 4
}
我正在处理许多动物API,我想将它们规范化为我自己的通用格式,如:

{
  common_name: "Tiger",
  latin_name: "Panthera tigris",
  limbs: {
    legs: 4,
    arms: 0
  }
}
比如说,在JavaScript中,这很简单:

normalizeAnimal = function(original){
  return {
    common_name: original.name.common,
    latin_name: original.name.latin,
    limbs: {
      legs: original.legs || 0,
      arms: original.arms || 0
    }
  }
}
但是Java呢?使用org.json中的JSONObject类,我可以进行如下操作:

public JSONObject normalizeAnimal(JSONObject original) throws JSONException{
  JSONObject name = original.getJSONObject("name");
  JSONObject limbs = new JSONObject();
  JSONObject normalized = new JSONObject();
  normalized.put("name_name", name.get("common"));
  normalized.put("latin_name", name.get("latin"));
  try{
    limbs.put("legs", original.get("legs");
  }catch(e){
    limbs.put("legs", 0);
  };
  try{
    limbs.put("arms", original.get("arms");
  }catch(e){
    limbs.put("arms", 0);
  };
  normalized.put("limbs", limbs);
  return normalized;
}
随着我正在处理的JSON对象变得越来越长、越来越深,情况变得更糟。除此之外,我正在与许多动物对象的提供者打交道,最终我将寻找一些简洁的配置格式来描述转换(比如,
“common\u name”:“name.common”,“frameds.legs”:“legs”


如何在Java中减少这个问题?

如果您要将它用于许多不同类型的对象,我建议使用反射,而不是手动序列化每个对象。通过使用反射,您不需要创建像normalizeAnimal这样的方法,只需创建一个方法或一个类来对json格式进行序列化

如果您搜索“MappingJSONJava”,您会发现一些有用的参考资料。像格森。以下是他们网站上的一个示例:



    class BagOfPrimitives {
      private int value1 = 1;
      private String value2 = "abc";
      private transient int value3 = 3;
      BagOfPrimitives() {
        // no-args constructor
      }
    }

    //(Serialization)
    BagOfPrimitives obj = new BagOfPrimitives();
    Gson gson = new Gson();
    String json = gson.toJson(obj);  
    ///==> json is {"value1":1,"value2":"abc"}

    ///Note that you can not serialize objects with circular references since that will result in infinite recursion. 

    //(Deserialization)
    BagOfPrimitives obj2 = gson.fromJson(json, BagOfPrimitives.class);   
    //==> obj2 is just like obj


使用像Gson或Jackson这样的库,将JSON映射到Java对象

所以你会有一个像豆子一样的

public class JsonAnima {
    private JsonName name;
    private int legs; 
}
public class JsonName {
    private String commonName;
    private String latinName;
}
它可以很容易地转换与任何图书馆与类似(杰克逊)

然后,您可以创建一个“转换器”,将JsonAnimal映射到您的动物类

这可能是一种方法。:)


一些链接:

格森:


Jackson:

纯Java解决方案都面临着处理源数据不可靠结构的挑战。如果您运行在JVM中,我建议您考虑使用Groovy来执行解析和源JSON的构建。结果看起来非常像您上面概述的Javascript解决方案:

import groovy.json.JsonBuilder
import groovy.json.JsonSlurper

def originals = [
  '{ "name": { "common": "Tiger", "latin": "Panthera tigris" }, "legs": 4 }',
  '{ "name": { "common": "Gecko", "latin": "Gek-onero" }, "legs": 4, "arms": 0 }',
  '{ "name": { "common": "Liger" }, "legs": 4, "wings": 2 }',
  '{ "name": { "common": "Human", "latin": "Homo Sapien" }, "legs": 2, "arms": 2 }'
]

originals.each { orig ->

  def slurper = new JsonSlurper()
  def parsed = slurper.parseText( orig )

  def builder = new JsonBuilder()
  // This builder looks a lot like the Javascript solution, no?
  builder { 
      common_name parsed.name.common
      latin_name parsed.name.latin
      limbs {
          legs parsed.legs ?: 0
          arms parsed.arms ?: 0
      }
  }

  def normalized = builder.toString()
  println "$normalized"
}
运行上面的脚本处理“锯齿”JSON(并非所有元素都具有相同的属性)和输出,如

{"common_name":"Tiger","latin_name":"Panthera tigris","limbs":{"legs":4,"arms":0}}
{"common_name":"Gecko","latin_name":"Gek-onero","limbs":{"legs":4,"arms":0}}
{"common_name":"Liger","latin_name":null,"limbs":{"legs":4,"arms":0}}
{"common_name":"Human","latin_name":"Homo Sapien","limbs":{"legs":2,"arms":2}}
你可以试试小java库

JsonValue json = JsonParser.parse(stringvariablewithjsoninside);
Jmom mom = Jmom.instance()
    .copy("/name/common", "/common_name", true)
    .copy("/name/latin", "/latin_name", true)
    .copy("/arms", "/limbs/arms", true)
    .copy("/legs", "/limbs/legs", true)
    .remove("/name")
    ;
mom.apply(json);
String str = json.toPrettyString("  ");

(可以在Java中运行JavaScript..我并不是特别建议它执行此任务,但这是一种[聪明的]方法;-)您试图通过此方法实现什么?如中所示,以相同的格式发送数据可以解决什么实际问题?因为JavaScript解释器不关心。@parsifal,我允许另一个开发人员将标准化动物插入他们的UI,而不必在他们的UI代码中进行解析。(它们也不是真正的动物。这是一个人为的例子。)您可以通过使用
if has(key)
而不是捕获异常来使用代码来改进JSONObject。我不推荐这样做。。。这不仅是不必要的自动序列化/反序列化,而且最终可能会产生更多的代码行。是的,我同意。无论如何,您可以使用注释将正确的属性映射到字段。:)+1 OP想让他的normalizeAnimal(JSONObject)代码“不那么糟糕”。Json是一种数据交换格式,典型的Java程序员只会在这种能力下使用Json和JSONObject。因此,您可以在输入时将Json转换为普通Java对象,在这些对象上执行所需的任何处理,如果这也是您的输出格式,则将其转换回Json。OP还需要一个简洁的基于配置的转换工具,为此,您可以尝试使用Dozer(它也在普通Java对象上运行)。我将建议使用Dozer的Gson/Jackson。为每种格式编写一个Java对象,然后使用Dozer将其中一种格式的字段映射到另一种格式的字段(如果需要,则反之亦然)。根据我的经验,当JSON具有“变量模式”或并非所有入站JSON对象都具有完全相同的结构时,对象映射不起作用。您最终不得不手动解析JSON,或者让某个框架将其转换为映射的映射。为此,我已经成功地使用了JacksonTreeModel:,但这仍然是一个小函数的大量代码。我建议使用Groovy或其他更具动态性的语言来实现这一点。
JsonValue json = JsonParser.parse(stringvariablewithjsoninside);
Jmom mom = Jmom.instance()
    .copy("/name/common", "/common_name", true)
    .copy("/name/latin", "/latin_name", true)
    .copy("/arms", "/limbs/arms", true)
    .copy("/legs", "/limbs/legs", true)
    .remove("/name")
    ;
mom.apply(json);
String str = json.toPrettyString("  ");