【问题标题】:Parse json to necessary object将 json 解析为必要的对象
【发布时间】:2014-10-23 13:32:15
【问题描述】:

在我的 Android 应用中,我有 json,它看起来像:

{
    "Records": [
        {
            "RowIndex": "0",
            "NameValue": {
                "Name": "PropertyName1",
                "Value": "PropertyValue1"
            }
        }{
            "RowIndex": "1",
            "NameValue": {
                "Name": "PropertyName2",
                "Value": "PropertyValue2"
            }
        }
    ]
}

我需要将这个 json 转换为对象,如下所示:

public class MyClass {
    public String PropertyName1;
    public String PropertyName2;
}

解析后的结果应该是:

public String PropertyName1 = "PropertyValue1";
public String PropertyName2 = "PropertyValue2";

基本上,第一个json相当于:

{
    "PropertyName1" : "PropertyValue1",
    "PropertyName2" : "PropertyValue2"
}

问题:如何在不使用 swith/case 的情况下解析第一个 json 来搜索必要的属性?

【问题讨论】:

  • JSON 看起来很别扭。你做了吗?如果是这样,我建议使用其他命名方案。做“PropertyName2”更自然:“PropertyValue2”。它使解析变得容易得多。
  • @RvdK,我知道,但不幸的是,我无法更改它(我使用现有的 API)。现在我只有一个想法 - 从现有的(如我的帖子中的第一个)创建新的 json(如我的帖子中的第二个),然后才 - 将第二个 json 分配给对象。
  • @downvoters,请发表评论...

标签: java android json


【解决方案1】:

恐怕你将不得不走上黑暗的反思之路。 您可以将 json 解析为具有名称值映射的中间对象。

然后你使用下面的代码(当然只是复制粘贴你需要的位)来循环键/值对的映射。对于每个键,查找所需的字段并进行设置。如果您保证只需要设置公共变量,那么您可以使用 getFields 并且可以跳过 setAccessible。

public class Test {
    public static void main(String[] argv) {
        MyClass myClass = new MyClass();
        Class<?> classObject = myClass.getClass();

//        Field fields[] = classObject.getFields(); // if you want to get only public fields.
        Field fields[] = classObject.getDeclaredFields(); // any field
        for(Field f : fields) {
            System.out.println(f.getName());
            try {
                // if member is private: security managers may object but the default java allows it
                f.setAccessible(true);
                f.set(myClass, "abc");
            } catch (IllegalAccessException e) {
                // handle access exception:
                e.printStackTrace();
            }
        }

        System.out.println("prop 1: " + myClass.PropertyName1);
        System.out.println("prop 2: " + myClass.PropertyName2);
    }


    public static class MyClass {
        public String PropertyName1;
        private String PropertyName2;
    }
}

实际上.. 有一种非反射方式,但这将取代您对您拥有的对象的实现。

如果你改变你的班级:

public class MyClass {
    public String PropertyName1;
    public String PropertyName2;
}

public class MyClass {
    private Map<String, String> properties = new HashMap<String, String>();
    public void setProperties(Map<String, String> props) { this.properties = props; }
    public String getPropertyName1() {
        return lookupProperty("PropertyName1");
    }
    public String getPropertyName2() {
        return lookupProperty("PropertyName2");
    }
    private String lookupProperty(String property) {
        if (properties.containsKey(property) {
            return properties.get(property);
        } else { 
            return null;
        }
    }
}

然后您可以将名称值映射解析为映射,并用它构造一个 myclass。 只是为了完整性而列出它,尽管更改域模型以适应 json 输入并不理想。

我会推荐任何一种方法来进行输入解析,然后将模型复制到您的实际域对象中,而不是在您的应用程序中使用 json-model。这样,如果 json 模型发生变化,您的域模型将不会改变。

【讨论】:

  • 我非常喜欢这个答案的后半部分。使用Map 是一个非常好的主意。
【解决方案2】:

我能想到的一种方法(听起来不太好)是实际制作一个与您返回的 JSON 响应相匹配的对象。然后,将 NameValue 对象映射到 MyClass

所以,像

public class NameValue {
   public string Name;
   public String Value;

   public MyClass getMyClass(){
         MyClass myClass = new MyClass();
         myClass.PropertyName2 = Value;
         return myClass;
   }
}

显然,您可以想出一个更好的方法来映射它。但这只是一个例子,如果我得到一个我并不特别关心的响应 JSON,我可能会做的事情。您可以类似地反转它(让MyClass 能够创建一个NameValue 对象),这样您就可以以正确的格式发回数据。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-07-27
    • 2014-10-17
    • 1970-01-01
    • 2012-09-25
    相关资源
    最近更新 更多