Android SQLite вставляет JSON в столбец TEXT с экранированием двойных кавычек

Я использую SQLite в приложении для Android, в котором, помимо прочего, хранится таблица, в которой записывается настроение пользователя. Схема таблицы показана ниже

CREATE TABLE moods
(
 dow INTEGER,
 tsn INTEGER,
 lato INTEGER,
 agitation TEXT DEFAULT '{}',
 preoccupancy TEXT DEFAULT '{}',
 tensity TEXT DEFAULT '{}',
 taps TEXT DEFAULT '{}'     
);

В отличие, скажем, от Postgres, SQLite не имеет выделенного jsonb тип хранения. Цитировать

Ограничения обратной совместимости означают, что SQLite может хранить только значения со значениями NULL, целыми числами, числами с плавающей точкой, текстом и BLOB-объектами. Невозможно добавить шестой тип "JSON".

Документация по расширению SQLite JSON1

На процессоре командной строки SQLite я могу заполнить эту таблицу с помощью простого оператора INSERT, такого как этот

INSERT INTO moods (dow,tsn,lato,agitation,preoccupancy,tensity,taps) 
VALUES(1,0,20,'{"A2":1}','{"P4":2}','{"T4":3}','{"M10":4}');

так как он принимает одинарные и двойные кавычки для строк.

Чтобы сделать то же самое в моем приложении Hybrid Android, я делаю следующее

String ag = JOString("A" + DBManage.agitation,1);
String po = JOString("P" + (DBManage.preoccupancy + 15),1);
String te = JOString("T"  + DBManage.tensity,1); 

который возвращает строки, такие как {"P4":2} и т. д. Мой следующий шаг заключается в следующем

ContentValues cv = new ContentValues();
cv.put("dow",0);
cv.put("tsn",1);
cv.put("lato",2);
cv.put("agitation",ag);
cv.put("preoccupancy",po);
cv.put("tensity",te);
long rowid = db.insert("moods",null,cv);

который работает. Однако, изучив сохраненные значения, я обнаружил, что на самом деле

{"dow":0,"tsn":5,"lato":191,"tensity":"{\"T0\":1}","agitation":" 
{\"A1\":1}","preoccupancy":"{\"P15\":1}","taps":"{}"}]

Если я не понимаю что-то здесь ContentValues.put или SQLiteDatabase.insert реализация взяла на себя обязательство избегать цитируемых строк. Возможно, этого следовало ожидать, учитывая, что польза от снижения SQLiteDatabase.insert маршрут с ContentValues защита от атак SQL-инъекций Однако в данном случае это помеха, а не помощь.

За исключением выполнения необработанного SQL через execSQL Есть ли другой способ получить JSON в таблицу базы данных SQLite здесь?


Я должен добавить, что простая замена двойных кавычек одинарными кавычками

String ag = JOString("A" + DBManage.agitation,1);
ag = ag.replaceAll("\"","'");

не будет работать после следующей попытки извлечь JSON из таблицы

SELECT ifnull((select json_extract(preoccupancy,'$.P4') from moods where dow = '1' AND tsn = '0'),0);

приведет к ошибке искаженного JSON, испускаемого расширением SQLite JSON1.

0 ответов

Другие вопросы по тегам