【问题标题】:converting json into java object for a array with mixed types将 json 转换为 java 对象,用于混合类型的数组
【发布时间】:2015-07-16 04:21:07
【问题描述】:

我的 json 字符串如下所示:

{
  "text": ["foo",1,"bar","2",3],
  "text1": "value1",
  "ComplexObject": {
   .....
   }
}

我有一个这样定义的 pojo:

class MyPojo {
 List<String> text;
 String text1;
 ComplexObject complexObject;
}

我使用 google gson 并且能够正确填充我的 java 对象。这里的问题是字段文本是一个混合类型(字符串和整数)的数组。所以那里的所有条目都转换为字符串,我无法确定数组中的哪些条目是字符串与 int。我不能使用 parseInt,因为原始数组中的条目可能有“2”和 3。

在转换成 java 对象后,有没有办法让我获得数组中字段的正确实例类型。

解决方案

所以我使用 JsonDeserializer 来实现使用 gson 的解决方案。然后我尝试使用杰克逊。猜猜jackson通过保留数据类型支持序列化/反序列化混合数组类型。

ObjectMapper mapper = new ObjectMapper();
MyPojo gmEntry = mapper.readValue(json, new TypeReference<MyPojo >(){});

而且我基本上可以获取 List 并执行 instanceof 来检查数据类型。

你真丢脸!!

【问题讨论】:

  • 棘手的情况。可能您可能已经尝试过,但是不能单独维护数据,即字符串和数字吗?
  • 没错,我不能单独维护
  • gson 不知道数据包含整数作为字符串以及整数的事实。基于 List 它将所有内容转换为字符串。一旦完成,似乎没有办法单独获取整数而不获取实际上是整数的字符串。在我看来是死路一条。
  • 我没有绑定到 gson。还有其他图书馆可以提供帮助吗?

标签: java json


【解决方案1】:

通过自定义类并添加类型适配器,您可以操作字符串(json.toString() 返回带有 '"' 引号,因此您可以查看它是否为字符串。

输出:(类似乎正确)

class test.Main$StringPojo pojo{object=foo}

类 test.Main$IntPojo pojo{object=1}

class test.Main$StringPojo pojo{object=bar}

class test.Main$StringPojo pojo{object=2}

类 test.Main$IntPojo pojo{object=3}

public static void main(final String[] args){


    String str = "{\n" +
            "  \"text\": [\"foo\",1,\"bar\",\"2\",3],\n" +
            "  \"text1\": \"value1\" }";

    GsonBuilder builder = new GsonBuilder();
    builder.registerTypeAdapter(pojo.class, new JsonDeserializer<pojo>() {
        @Override
        public pojo deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
            try {
                return new IntPojo(Integer.parseInt(json.toString()));
            } catch (Exception e) {
                return new StringPojo(json.getAsString());
            }
        }
    });
    MyPojo myPojo = builder.create().fromJson(str, MyPojo.class);
    for (pojo pojo : myPojo.text) {
        System.out.println(pojo.getClass() + " " + pojo.object);
    }
}

public static abstract class  pojo{
    protected Object object;

    public pojo() {
    }

    @Override
    public String toString() {
        return "pojo{" +
                "object=" + object +
                '}';
    }
}

public static class StringPojo extends pojo{
    public StringPojo(String str) {
        object = str;
    }
}

public static class IntPojo extends pojo{

    public IntPojo(int intt) {
        this.object = intt;
    }
}
public static class MyPojo {
    List<pojo> text;
    String text1;
}

【讨论】:

  • 你能用 java 7 等价物更新代码库吗?
  • 没关系能够在 java7 中使用它。这看起来很有希望。让我试试这个,然后告诉你。
  • 当您自己创建对象时,您可以根据需要对其进行初始化(您不必使用抽象类),我已经对其进行了编辑,使其成为 java 7
  • 这和我提议的一样!
  • 您提出了一种数据结构,而不是一种使用 gson 解析数组中混合类型的方法。使用正在使用的库运行代码时,抛出异常
【解决方案2】:

正如您所写 - 您定义:List&lt;String&gt; text; 但该列表也包含整数。

Java 是强类型的,请考虑将列表声明为 List&lt;Object&gt;(不太可取)或创建仅包含单一类型变量的 JSON 列表(更可取)。

【讨论】:

  • 将其定义为 List 的问题是我无法确定 List 的哪些元素是整数还是字符串。 getClass() 返回 java.lang.Object。
  • 当然因为那是 List 的类型 :) 这也是我写它不是最好的方式的原因 - 你 可以 这样做,但你会有做丑陋的事情以使其发挥作用。例如:Object[] a = {"a", 1}; System.out.println(Integer.valueOf((String.valueOf(a[1])))); 然后用try/catch 包围它,以防它不是int 等等。
  • 就像我在帖子中提到的那样,我不能使用 Integer.valueOf 因为我的 json 数组可以说“3”和 2,例如["3",2]
  • 可以获取 JSON 作为字符串并自己解析它,查找每个项目是否被引号包围。但是您必须实现它,而不是能够使用现有的 JSON 库。正如我已经说过的,这是一种不好的做法,代码看起来很丑(以及维护它不会很有趣......)。更好的方法是重新考虑架构并传递包含相同类型的 JSON 数组。请记住,Java 是强类型的,不像 Javascript/Python/Ruby 等。
  • 猜猜杰克逊很容易有趣地支持这一点。
【解决方案3】:

您可以创建一个抽象类ItemType(用作数组项类型)并从中继承两个包装类:一个用于 int 类型,另一个用于 string 类型。

abstract class ItemType {
    protected Object value;
}
class IntType extends ItemType {
    IntType(Integer value){
        this.value = value;
    }
}
class StringType extends ItemType {
    IntType(String value){
        this.value = value;
    }
}

试试这个List&lt;ItemType&gt; text;

【讨论】:

  • 我试过这个但是它抛出了一个异常“com.google.gson.JsonParseException: Expecting object found: foo”
【解决方案4】:

【讨论】:

  • 我看过了。给出的示例是将数组作为顶级元素。而在我的情况下不是。所以基本上我将不得不自己解析 json 字符串,然后弄清楚它是 JsonArray 还是 JsonObject 并且无法利用直接 json 到 java 对象转换的好处。同样在给出的示例中,看起来数组中元素的顺序是预先定义的,这不是我的情况。
【解决方案5】:

不确定这是否是您需要的,但这是我用于解析 JSON 的代码。

static public void newsParser(String urlString, String targetObject) throws FileNotFoundException, IOException
    {

        URL url = new URL(urlString);

        JSONParser parser=new JSONParser();


           BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()));



           Object obj;
        try 
        {
            obj = parser.parse(br);         
            //JSONObject jsonObject = (JSONObject) obj;
            JSONArray jsonArray = (JSONArray) obj;

            Iterator<?> i = jsonArray.iterator();

            while (i.hasNext())
            {
                slide = (JSONObject) i.next();
                newsInfo = (String)slide.get(targetObject);   
                System.out.println(newsInfo);
                newsTitles.add(newsInfo);


            }
        } 
        catch (ParseException e) 
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

【讨论】:

    猜你喜欢
    • 2017-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多