Обработка нулевых указателей из JsonReader
Я использую JsonReader для получения большого количества данных с веб-сайта и сохранения в БД. Между прочим, всякий раз, когда читатель не находит значение для объекта, он завершается ошибкой и прекращает выполнение.
Это ошибка, которую я имею;
System.err﹕ java.lang.IllegalStateException: Expected a string but was NULL at line 1 column 359337 path $[19].date
Даже если указанное значение недоступно, кажется, что все объекты, загруженные до появления ошибки, тоже теряются и не сохраняются в БД. Есть ли способ справиться с этими ошибками и сохранить объекты, которые были загружены до сих пор? Я установил JsonReader как снисходительный.
Это часть метода, которая анализирует данные:
private Post read(JsonReader reader) throws Exception {
reader.beginObject();
while (reader.hasNext()) {
String name = reader.nextName();
switch (name) {
case TITLE:
mTitle = new StringBuilder();
mTitle.append(reader.nextString());
break;
case AUTHOR:
if (reader.hasNext()) {
JsonToken peek = reader.peek();
if (peek == JsonToken.NULL) {
reader.skipValue();
} else {
reader.beginObject();
while (reader.hasNext()) {
String enclosedName = reader.nextName();
switch (enclosedName) {
case NAME:
mAuthor = new StringBuilder();
mAuthor.append(reader.nextString());
break;
case AVATAR:
mAvatar = new StringBuilder();
mAvatar.append(reader.nextString());
break;
default:
reader.skipValue();
break;
}
}
reader.endObject();
}
}
break;
case CONTENT:
mDescription = new StringBuilder();
mDescription.append(reader.nextString());
break;
case URL:
mEntryLink = new StringBuilder();
mEntryLink.append(reader.nextString());
break;
case DATE:
mDateStringBuilder = new StringBuilder();
mDateStringBuilder.append(reader.nextString());
break;
case GUID:
mGuid = new StringBuilder();
mGuid.append(reader.nextString());
break;
case FEATURED_IMAGE:
if (reader.hasNext()) {
JsonToken look = reader.peek();
if (look == JsonToken.NULL) {
reader.skipValue();
} else {
mFeaturedImage = new StringBuilder();
reader.beginObject();
while (reader.hasNext()) {
String itemToLookFor = reader.nextName();
switch (itemToLookFor) {
case SOURCE:
mFeaturedImage.append(reader.nextString());
break;
default:
reader.skipValue();
break;
}
}
reader.endObject();
}
}
break;
case TERMS:
if (reader.hasNext()) {
JsonToken check = reader.peek();
if (check == JsonToken.NULL) {
reader.skipValue();
} else {
reader.beginObject();
while (reader.hasNext()) {
String stuff = reader.nextName();
switch (stuff) {
case CATEGORIES:
reader.beginArray();
itemCategory = new StringBuilder();
while (reader.hasNext()) {
reader.beginObject();
while (reader.hasNext()) {
String item = reader.nextName();
switch (item) {
case NAME:
itemCategory.append(reader.nextString()).append(",");
break;
default:
reader.skipValue();
break;
}
}
reader.endObject();
}
reader.endArray();
break;
case TAGS:
reader.beginArray();
itemTags = new StringBuilder();
while (reader.hasNext()) {
reader.beginObject();
while (reader.hasNext()) {
String item = reader.nextName();
switch (item) {
case NAME:
itemTags.append(reader.nextString()).append(",");
break;
default:
reader.skipValue();
break;
}
}
reader.endObject();
}
reader.endArray();
break;
default:
reader.skipValue();
break;
}
}
reader.endObject();
}
}
break;
default:
reader.skipValue();
break;
}
}
reader.endObject();
return new Post(mAuthor.toString(), mAvatar.toString(), mDateStringBuilder.toString(), mTitle.toString(), mEntryLink.toString(), mDescription.toString(), mGuid.toString(), mFeaturedImage.toString(), itemTags.toString(), itemCategory.toString());
}
1 ответ
Я думал, может быть, вы не проверяли NULL
элементы, которые, кажется, имеют место.
В какой-то момент вы используете:
JsonToken check = reader.peek();
if (check == JsonToken.NULL) {
Это правильно. Однако в других местах вы просто получаете String
:
mDescription.append(reader.nextString());
Во всех местах вы получаете String
необходимо проверить, есть ли на самом деле неожиданный тип (например, NULL
). В таких случаях вам необходимо применить соответствующий код для локализации ошибок.
Кстати, вам действительно не нужно создавать все эти StringBuilder
s. Так как вы кладете только один String
в него после каждой инициализации. Вы бы сэкономили много времени, просто используя строку. Если вы намерены записать все содержимое в StringBuilder
для каждого типа, затем вам нужно инициализировать их перед началом цикла.