Почему я постоянно получаю null вместо значения строки в JSON?
Я пробовал две библиотеки для работы с JSON: GSON и FastJson.
JSON (кусок):
{
...
"Layout1BottomContent": ["Selection'@string/Selection'", "Folder'@string/New'", "*NewDir'@string/NewDir'", "*NewFile'@string/NewFile'", "Folder'Open'", "*OpenAssoc'@string/OpenAssoc'", "*OpenWith'@string/OpenWith'", "*OpenAs'@string/OpenAs'", "Delete'@string/Delete'", "Copy'@string/Copy'", "Compress'@string/Compress'", "Extract'@string/Extract'", "Folder'Menu'"],
"Layout1BottomAppearance": ["60", "Fit", "Center", "Rounded", "Icon", "Expandable"],
"Layout1Top": "NormBarPinned",
...
}
Пытался парсить через FastJson:
public class MainPageBasicLayout extends AppCompatActivity {
int Layout1BottomLvl1Num = 0;
String[] Layout1BottomLvl1Features = new String[9];
String[] Layout1BottomLvl1Items = new String[9];
//JSON Fields
@JSONField
String Layout1Bottom = null;
@JSONField
List<String> Layout1BottomContent;
@JSONField
List<String> Layout1BottomAppearance;
@JSONField
String ExitBehavior;
@JSONField
int Layout1BottomNum = 0;
public MainPageBasicLayout() {
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_page);
//Get JSON file content
String JSON = null;
try {
JSON = new CfgMgr().GetJsonFileContent(this);
} catch (IOException e) {
e.printStackTrace();
}
MainPageBasicLayout Obj = com.alibaba.fastjson.JSON.parseObject(JSON, MainPageBasicLayout.class);
}
Потом пытался через GSON:
public class MainPageBasicLayout extends AppCompatActivity {
int Layout1BottomLvl1Num = 0;
String[] Layout1BottomLvl1Features = new String[9];
String[] Layout1BottomLvl1Items = new String[9];
//JSON Fields
@Expose
String Layout1Bottom = null;
@Expose
List<String> Layout1BottomContent;
@Expose
List<String> Layout1BottomAppearance;
@Expose
String ExitBehavior;
@Expose
int Layout1BottomNum = 0;
public MainPageBasicLayout() {
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_page);
//Get JSON file content
String JSON = null;
try {
JSON = new CfgMgr().GetJsonFileContent(this);
} catch (IOException e) {
e.printStackTrace();
}
GsonBuilder builder = new GsonBuilder();
Gson gson = builder.excludeFieldsWithoutExposeAnnotation().create();
MainPageBasicLayout Obj = gson.fromJson(JSON, MainPageBasicLayout.class);
}
А затем я пытаюсь выполнить Integer.parseInt(Layout1BottomAppearance.get(0)), но получаю:
NullPointerException: Attempt to invoke interface method 'java.lang.Object java.util.List.get(int)' on a null object reference
P.S. Код GetJsonFileContent:
public String GetJsonFileContent(Context Context) throws IOException {
File Cfg = new File("/data/data/mate.files/", "Cfg.json");
String PreparedData = "";
int CfgLength = CfgStr.getBytes().length;
char[] Char;
Char = new char[CfgLength];
InputStreamReader InputRdr = new InputStreamReader(Context.openFileInput("Cfg.json"));
InputRdr.read(Char, 0, CfgLength);
int Counter = 0;
//Convert char array to String
for (Counter = 0; Counter != CfgLength; Counter++) {
PreparedData = PreparedData + Char[Counter];
}
InputRdr.close();
return PreparedData;
}
Ответы (1 шт):
Объяснение ошибки
Я полагаю, что все из-за того, что Вы извлекаете данные из JSON'да и кладёте их в один объект, а потом пытаетесь получить их из другого.
На примере:
MainPageBasicLayout Obj = com.alibaba.fastjson.JSON.parseObject(JSON, MainPageBasicLayout.class);
Вы извлекаете данные из JSON и сохраняете их в Obj
После чего вы вызываете следующий код:
Integer.parseInt(Layout1BottomAppearance.get(0))
Здесь не указано, где именно он расположен, но насколько могу себе представить он расположен внутри MainPageBasicLayout, а если это так, то в двух вышеприведенных строках вы обращаетесь к разным объектам.
Отсюда и следует NullPointerException:
Вы сохранили данные в Obj, а потом пытаетесь получить их же в this.
Вы должны были обращаться:
Obj.Layout1BottomAppearance.get(0)
а вместо этого обратились
this.Layout1BottomAppearance.get(0)
(ссылка this используется неявно и здесь я ее подставил, чтобы вы понимали, что это разные объекты )
Рекомендации
Я бы предостерег Вас от попыток вручную создавать и манипулировать объектами Activity - оставьте это на откуп Android'у
Отсюда следует что не стоит пытаться из JSON'а создать Activity.
Если хотите что-то извлечь из JSON и применить к Activity:
- Создайте отдельный класс настроек Activity, например ActivitySettings
- Извлеките данные из JSON в объект данного типа.
- Примените настройки используя полученный объект
Пример
Создаем класс описывающий модель хранимых в JSON данных
public class ActivitySettings {
@Expose
String Layout1Bottom = null;
@Expose
List<String> Layout1BottomContent;
@Expose
List<String> Layout1BottomAppearance;
@Expose
String ExitBehavior;
@Expose
int Layout1BottomNum = 0;
// ...
}
Ну и потом извлекаем:
GsonBuilder builder = new GsonBuilder();
Gson gson = builder.excludeFieldsWithoutExposeAnnotation().create();
ActivitySettings settings = gson.fromJson(JSON, ActivitySettings.class);
результат в дебаггере
как видим в settings прекрасно хранятся значения из Json.
И потом вы можете их брать и использовать как вам нужно.
Замечание
Вы часто используете имена
- переменных (
Obj), - полей (
ExitBehavior), - методов (
GetJsonFileContent())
начинающихся с заглавной буквы
В Java так делать нельзя!
В Java есть конвенции, которые четко определяют, что названия классов всегда должны начинаться с заглавной, а переменных и методов с прописной.
Если боитесь за различие название полей в классе и JSON'е - используйте аннотацию @SerializedName с указанием названия поля в JSON
public class ActivitySettings {
@Expose
@SerializedName("Layout1Bottom")
String layout1Bottom = null;
@Expose
@SerializedName("Layout1BottomContent")
List<String> layout1BottomContent;
@Expose
@SerializedName("Layout1BottomAppearance")
List<String> layout1BottomAppearance;
@Expose
@SerializedName("ExitBehavior")
String exitBehavior;
@Expose
@SerializedName("Layout1BottomNum")
int layout1BottomNum = 0;
// ...
}
