【问题标题】:Create, Write, Edit JSON file in Android Studio在 Android Studio 中创建、写入、编辑 JSON 文件
【发布时间】:2020-10-09 22:27:46
【问题描述】:

我想在手机的内部存储器中创建一个 JSON 文件来存储数据。 我希望能够将对象(“configX”)添加到文件中,然后读取数据。

它应该看起来像这样:

{

  "config1": {

    "component1": "url",
    "component2": "url",
    "component3": "url"

  },

  "config2": {

    "component1": "url",
    "component2": "url",
    "component3": "url"

  }

}

我可以像这样创建一个 JSON 文件:

public void saveToJson(){
    JSONObject json = new JSONObject();
    try {
        json.put("component1", "url");
        json.put("component2", "url");

        String jsonString = json.toString();
        
        FileOutputStream fos = this.openFileOutput("jsonfile", Context.MODE_PRIVATE);
        fos.write(jsonString.getBytes());
        fos.close();

        Log.d("JSON" , json.toString());

    } catch (IOException | JSONException e) {
        e.printStackTrace();
    }
}

但是如何将组件放在配置对象中?以及如何检索数据?

编辑 1:

https://stackoverflow.com/a/62474912/11652860

感谢您提供非常详细的答案,我做错了。我有一个活动,我将数据放入并保存到 json 文件中:

public class Data {

        private Map<String, Map<String, String>> map;

        public Data() {

        }

        public Data(Map<String, Map<String, String>> map) {
            this.map = map;
        }

        public Map<String, Map<String, String>> getMap() {
            return map;
        }

        public void setMap(Map<String, Map<String, String>> map) {
            this.map = map;
        }

    }
Map<String, String> config1 = new HashMap<>();
config1.put("component1", "url1");
config1.put("component2", "url1");
config1.put("component3", "url1");

Map<String, Map<String, String>> map = new HashMap<>();
map.put("config1", config1);

Data data = new Data(map);

Gson gson = new Gson();
String json = gson.toJson(data);

FileOutputStream fos = null;
 try {
fos = webViewActivity.this.openFileOutput("jsonfile", Context.MODE_PRIVATE);
} catch (FileNotFoundException e) {
 e.printStackTrace();
}
 try {
 fos.write(json.getBytes());
} catch (IOException e) {
  e.printStackTrace();
}
 try {
 fos.close();
} catch (IOException e) {
 e.printStackTrace();
}

还有一个我加载数据的片段:

public class Data {

        private Map<String, Map<String, String>> map;

        public Data() {

        }

        public Data(Map<String, Map<String, String>> map) {
            this.map = map;
        }

        public Map<String, Map<String, String>> getMap() {
            return map;
        }

        public void setMap(Map<String, Map<String, String>> map) {
            this.map = map;
        }

    }
 public void load(){
        FileInputStream fis = null;

        try {

            fis = getContext().openFileInput("jsonfile.txt");
            InputStreamReader isr = new InputStreamReader(fis);
            BufferedReader br = new BufferedReader(isr);

            StringBuilder sb = new StringBuilder();
            String text;

            while ((text = br.readLine()) != null){
                sb.append(text).append("\n");

                Gson gson = new Gson();

                String json = gson.toJson(text);
                Data data = gson.fromJson(json, Data.class);

                String url = data.getMap().get("config1").get("component1");

                frameTV.setText(url);

            }


        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fis != null){
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

保存和加载部分肯定是错误的,但是它们可以从文本文件中取出文本

编辑 2:

我发现了问题,我没有正确加载和保存:

正在保存:

String filename = "jsonfile.txt";

FileOutputStream outputStream;

try {
   outputStream = openFileOutput(filename, Context.MODE_PRIVATE);
   outputStream.write(json.getBytes());
   outputStream.close();
} catch (Exception e) {
   e.printStackTrace();
}

正在加载:

FileInputStream fis = getContext().openFileInput("jsonfile.txt");
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader bufferedReader = new BufferedReader(isr);
StringBuilder sb = new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null) {
    sb.append(line);
}

String json = sb.toString();

Gson gson = new Gson();
Data data = gson.fromJson(json, Data.class);
String priceURL = data.getMap().get("config1").get("url1");

编辑 3:

我现在的问题是我需要创建一次文件然后检查文件是否存在,如果存在我需要检查 config1 是否存在,如果不存在我需要将配置放入文件中。

但我无法检查 config1 是否存在,因为我得到:java.lang.NullPointerException: Attempt to invoke virtual method 'java.util.Map com.a.app.ui.app.appFragment$Data.getMap()

我通过以下方式检查它是否存在:

Boolean configTest = data.getMap().containsKey("config1");
if(!configTest){}

如何在不出现 NullPointerException 的情况下创建文件并检查数据?

谢谢你帮助我!

【问题讨论】:

    标签: java android json file android-studio


    【解决方案1】:

    Google 的 Gson 库在这种情况下会有所帮助。

    1. 在您的 radle 文件中添加对 Google Gson 的依赖项。
        dependencies {
          implementation 'com.google.code.gson:gson:2.8.6'
        }
    
    1. 为您的数据容器创建一个类
        public class Data {
    
            private Map<String, Map<String, String>> map;
    
            public Data() {
            }
    
            public Data(Map<String, Map<String, String>> map) {
                this.map = map;
            }
    
            public Map<String, Map<String, String>> getMap() {
                return map;
            }
    
            public void setMap(Map<String, Map<String, String>> map) {
                this.map = map;
            }
        }
    
    1. 向您的班级添加数据
        Map<String, String> config1 = new HashMap<>();
        config1.put("component1", "url1");
        config1.put("component2", "url1");
        config1.put("component3", "url1");
    
        Map<String, String> config2 = new HashMap<>();
        config2.put("component1", "url1");
        config2.put("component2", "url1");
        config2.put("component3", "url1");
    
        Map<String, Map<String, String>> map = new HashMap<>();
        map.put("config1", config1);
        map.put("config2", config2);
    
        Data data = new Data(map);
    
    1. 从数据类中获取 gson
    Gson gson = new Gson();
    String json = gson.toJson(data);
    
    1. 您现在可以将此 json 以文本格式保存在文件中。

    2. 现在读取时,将文本文件的内容加载到一个字符串中,比如“jsonString”。

    3. 将 jsonString 反序列化为 Java 对象

    Data data = gson.fromJson(json, Data.class);
    
    1. 访问配置
    String url = data.getMap().get("config1").get("component1");
    
    1. 添加新配置
        Map<String, String> config3 = new HashMap<>();
        config3.put("component1", "url1");
        config3.put("component2", "url1");
        config3.put("component3", "url1");
    
        data.getMap().put("config3", config3);
    
    
    1. 再次按照这些步骤保存配置

    2. 或者您可以手动编辑文本文件以根据预定义的格式添加配置。

        {
           "maps":{
              "config2":{
                 "component1":"url1",
                 "component2":"url1",
                 "component3":"url1"
              },
              "config1":{
                 "component1":"url1",
                 "component2":"url1",
                 "component3":"url1"
              }
           }
        }
    

    【讨论】:

    • 唯一的问题是我不能添加组件 4,5,6 因为它们替换了组件 1,2,3 :map.put("config1", config1); 是问题我该如何解决这个问题?
    • 如果你想在 config1 中添加更多的组件,在加载数据类后只需执行 data.getMap().get("config1").put("component4", "url4");并重新保存文件。提醒一下,您也可以通过编辑json文件并在config1中添加另一个键值对来手动添加组件
    • 由于某种原因,当我在其他模拟器上运行代码时出现此错误:jsonfile.txt: open failed: ENOENT (No such file or directory) 看起来它没有创建文本文件,但是当我尝试创建它时它仍然不起作用,我得到java.lang.NullPointerException: Attempt to invoke virtual method 'java.util.Map com.a.app.ui.app.appFragment$Data.getMap()' on a null object reference
    • 这可能是因为在更改设备时,json文件首先不存在。如果您创建一个空文件,反序列化将失败,导致空指针异常,因为它根本无法从空文件创建对象。您需要至少手动初始化对象一次然后保存它。如果您的配置文件不需要每次更改设备时都更改,您可以简单地将文件放在您的资产文件夹中,这样可以将文件与 apk 打包。
    • 谢谢,我用File file = getContext().getFileStreamPath(FILE_NAME);然后if(!file.exists()){}解决了这个问题,如果文件不存在我创建config1(就像你给我看的那样)并把它放在map然后创建并保存文件。
    【解决方案2】:

    这是在单个 JSON 对象中创建多个对象的方式:

    //Creating first Object
    JSONObject config1 = new JSONObject();
    try {
        json.put("component1", "url");
        json.put("component2", "url");
        json.put("component2", "url");
        }
    catch (JSONException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    
    //Creating second object
    JSONObject config2 = new JSONObject();
    try {
        json.put("component1", "url");
        json.put("component2", "url");
        json.put("component2", "url");
        }
    catch (JSONException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    
    JSONObject finalJSON = new JSONObject();
    try {
        //Adding both objects in one single object
        json.put("config1", config1);
        json.put("config2", config2);
    
        String jsonString = finalJSON.toString();
    
        FileOutputStream fos = this.openFileOutput("jsonfile", Context.MODE_PRIVATE);
        fos.write(jsonString.getBytes());
        fos.close();
    
        Log.d("JSON" , json.toString());
    
    } catch (IOException | JSONException e) {
        e.printStackTrace();
    }
    

    这将为您提供所需的输出。此外,如果您想将任何对象设为数组,您可以使用JSONArray

    【讨论】:

      【解决方案3】:

      请考虑使用https://github.com/google/gson。您将使用类实例而不是 JSONObject。方便多了。

      只是为了让您了解您可以做什么:

      public class TestClass {
          private final Map<String, String> config1;
          private final Map<String, String> config2;
      
          public TestClass(Map<String, String> config1, Map<String, String> config2) {
              this.config1 = config1;
              this.config2 = config2;
          }
      }
      
      
              Gson gson = new GsonBuilder().setPrettyPrinting().create();
      
              Map<String, String> config1 = new HashMap<String, String>();
              config1.put("hello1.1", "world1.1");
              config1.put("hello1.2", "world1.2");
      
              Map<String, String> config2 = new HashMap<String, String>();
              config2.put("hello2.1", "world2.1");
              config2.put("hello2.2", "world2.2");
      
              TestClass testClass = new TestClass(config1, config2);
      
              Log.d("zzz", gson.toJson(testClass));
      

      以上打印:

          {
            "config1": {
              "hello1.1": "world1.1",
              "hello1.2": "world1.2"
            },
            "config2": {
              "hello2.1": "world2.1",
              "hello2.2": "world2.2"
            }
          }
      

      您可以返回并在 json 字符串和实体本身之间进行强制。要进行编辑,您只需要使用对象 - 自然而方便的方式。

      【讨论】:

        猜你喜欢
        • 2019-01-01
        • 2020-02-19
        • 1970-01-01
        • 1970-01-01
        • 2014-10-07
        • 2018-01-01
        • 2014-05-08
        • 2015-06-11
        • 1970-01-01
        相关资源
        最近更新 更多