Страницы

Поиск по вопросам

понедельник, 3 июня 2019 г.

Как убрать кавычки в JSON?

У меня есть БД из нее получаю JSON следующим способом
String DB_PATH = "/data/data/com.example.apps/databases/"; String myPath = DB_PATH + DBHelper.DATABASE_NAME;// Set path to your database String myTable = DBHelper.TABLE_CONTACT;//Set name of your table SQLiteDatabase myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
String searchQuery = "SELECT * FROM " + myTable; Cursor cursor = myDataBase.rawQuery(searchQuery, null );
JSONArray json = new JSONArray(); cursor.moveToFirst(); while (cursor.isAfterLast() == false) { int totalColumn = cursor.getColumnCount(); JSONObject rowObject = new JSONObject();
for(int i=0 ; i< totalColumn ; i++) { if(cursor.getColumnName(i) != null) { try { if(cursor.getString(i) != null) { Log.d("TAG_NAME", cursor.getString(i)); rowObject.put(cursor.getColumnName(i), cursor.getString(i)); } else { rowObject.put(cursor.getColumnName(i), ""); } } catch(Exception e) { Log.d("TAG_NAME", e.getMessage()); } } } json.put(rowObject); cursor.moveToNext(); } cursor.close(); Log.d("TAG_NAME_ALL", json.toString()); return json.toString();
JSON получается какой необходим, за исключением одного значения latlng
Я получаю - "latlng":"[54.601530521,55.918132215051]"
Нужно получить - "latlng":[54.601530521,55.918132215051]
Как избавиться от кавычек?


Ответ

из комментарий и оригинал из stackoverflow.com

Если вам нужно быстро перевести строку на double, хоть и с грязным кодом, тогда вы можете сделать так:
String s = "[12.3456789,98.7654321]"; String trimmed = s.substring(1, s.length()-1); String[] parts = trimmed.split(","); double lat = Double.parseDouble(parts[0]); double lng = Double.parseDouble(parts[1]); Log.d("latlng", "lat="+lat+" lng="+lng);
Это не красиво, но работает.

Predicate и Func в качестве T

Есть List< Func< string>> нужно вызвать List.RemoveAll().Туда нужно передать Predicate< T>. нужно удалить только определнные функции. На MSDN Видел пример с Point, но попытка переделать аналогично под Func не получается. В чем проблема?
List> _list; public MainWindow() { _list = new List>(); _list.Add(this.test); _list.Add(this.test2); _list.Add(this.test); _list.Add(this.test2); _list.Add(this.test);
Predicate> pre = ValidateFunc(test2,nameof(test2));// тут функция и подчеркивается с ошибкой }
private static bool ValidateFunc(Func obj,string targetName) { return targetName == nameof(obj); }
string test() { textBox.Text += " 2"; return ""; } string test2() { textBox.Text += " 3"; return ""; }
Ошибка:Не удается неявно преобразовать тип "bool" в "System.Predicate< System.Func< string>>"
Если как на MSDN без параметров то ошибка такая: Нет перегруженного метода для "ValidateFunc", который соответствует делегату "Predicate< Func< string>>"


Ответ

Я предлагаю такой вариант:
Predicate> pre = item => item == this.test;
В частности, при использовании этого предиката в качестве аргумента метода _list.RemoveAll, из коллекции _list будут удалены все вхождения метода test
Либо так, если вместо ссылки на метод вы желаете использовать строку с именем метода:
Predicate> pre = item => item.Method.Name == "test";
А назначение вашего метода ValidateFunc мне понять не удалось. Вы в нем сравниваете строку targetName с nameof(obj) (то есть со строковой константой "obj").

git pull accept theirs/ours

Можно ли как-то заставить git во время pull-а использовать стратегию слияния theirs для конкретной директории? Но если конфликты возникнут в других местах - пусть предоставить мне возможность решать.
Сейчас в голову приходит только такое: делаем hook, который отрабатывает после pull-а, и запускает git checkout --theirs {моя директория}


Ответ

на основе ответа: Simple tool to 'accept theirs' or 'accept mine' on a whole file using git

для частичной автоматизации можно, например, использовать псевдонимы:
$ git config --global alias.accept-ours = "!f() { [ -z \"$@\" ] && set - '.'; git checkout --ours -- \"$@\"; git add -u -- \"$@\"; }; f" $ git config --global alias.accept-theirs = "!f() { [ -z \"$@\" ] && set - '.'; git checkout --theirs -- \"$@\"; git add -u -- \"$@\"; }; f"
и при возникновении конфликта после git pull для файлов/каталогов, которые должны быть ours, выполнить:
$ git accept-ours -- файлы/каталоги ...
а для тех, что должны быть theirs
$ git accept-theirs -- файлы/каталоги ...

Как реализовать заглушку метода поиска в базе данных для тестового контекста?

Изолирую зависимости от реальной БД при написании модульных тестов в проекте. Интерфейс репозитория имеет следующий вид:
public interface IRepository { T Find(int id) where T: class; }
В реальном контексте метод реализован следующим образом:
public ConcreteDBContext : DBContext, IRepository { //some code public T Find(int id) where T : class { return this.Set.Find(id); } }
Вопрос: как правильно реализовать такой метод в FakeDBContext? И от чего наследовать сам контекст, кроме самого интерфейса IRepository?


Ответ

Если в местах, где вы используете db context, зависимость имеет тип IRepository, то вам достаточно наследовать заглушку от этого интерфейса (для этого зависимости и интерфейсы и нужны :)). Как правило, для каждого теста вам нужна будет своя реализация метода Find. Поэтому правильнее говорить о моках.
Самый правильный способ работать с моками -- использовать мок-фреймворки. Их великое множество: Moq, RhinoMock, NSubstitute и проч. Синтаксис их будет немного отличаться, однако суть работы с моками всегда одна:
Создаем мок-объект. Устанавливаем, что должен возвращать нужный нам метод мок-объекта при вызове с такими-то параметрами. Проверяем, что нужный нам метод был вызван (опционально).
Например, с использованием NSubstite это будет выглядеть так:
var personId = 1;
var repo = Substitute.For(); // для id = 1 возвращаем объект repo.Find(personId).Returns(new Person { Name = "John", LastName = "Doe" }); // для всех остальных id возвращаем null repo.Find(Arg.Is(a => a != 1)).Returns(null);
var someObjectThatUsesRepo = new SomeObjectThatUsesRepo(repo); someObjectThatUsesRepo.SomeMethod();
// проверяем, что метод вызвался ровно один раз repo.Received(1).Find(personId);

Обработчик проваленного теста

Производится юнит-тестирование usb-устройства (CDC). Тест открывает устройство, формирует запрос, отправляет его устройству, проверяет ответ, закрывает устройство. В случае, если тест провален, закрытие устройства не выполнится, и, следовательно, все последующие тесты также будут провалены, так как не смогут открыть устройство. В связи с этим вопрос: есть ли способ установить обработчик (handler, hook) проваленного теста, который бы выполнял освобождение ресурсов, запрошенных тестирующей функцией?
Тесты создаются в Visual Studio, тип проекта c++ unit test.


Ответ

Ваши ответы подсказали мне, в какой области искать верный ответ. В Visual Studio в Native Unit test методы до и после тестирования объявляются следующим образом:
TEST_METHOD_INITIALIZE(methodName) { // method initialization code }
TEST_METHOD_CLEANUP(methodName) { // test method cleanup code }
Внутри этих методов можно генерировать исключения и вызывать функции из статического класса Assert.
Больше информации здесь: MSDN

TSQL, “простой некластеризованный индекс”

Есть несколько индексов такого вида:
CREATE INDEX IX_ProductVendor_VendorID ON Purchasing.ProductVendor (VendorID);
На MSDN здесь (в разделе "примеры", первый пример) сказано, что это "простой некластеризованный индекс". Что это значит? Обычный первичный ключ? Может быть, глупый вопрос, но для меня не очевидно, хотелось бы быть уверенным.


Ответ

На Хабре есть аааааабалденная статья на тему индексов. Очень советую.
Если вкратце, то:
Индекс использует дерево для быстрого обращения к данным. У кластеризованного индекса в листьях дерева лежат сами строки данных. В силу природы дерева данные хранятся в уже отсортированном виде, поэтому кластеризованный индекс может быть только один. У некластеризованного индекса в листьях дерева лежат указатели на строки данных, т.е. для чтения данных необходима еще одна операция. Т.о. кластеризованных индексов у таблицы может быть несколько.
Что это значит? Обычный первичный ключ?
Понятие первичного ключа в общем-то не связано с индексом. В таблице может быть колонка, являющаяся первичным ключом, но без индекса. Однако на первичные ключи как правило создают кластеризованный индекс. В вашем вопросе VendorID это скорее просто foreign key -- на них обычно создают некластеризованные индексы.

Как правильно использовать реляции в Yii2?

Интересует как правильно использовать реляции, создавать индексы в таблицах, внешние ключи и как все это потом использовать через hasOne() и hasMany(). Буду предельно конкретен и распишу вопрос максимально широко (мало ли кому потом пригодится). Попрошу ответить как можно конкретнее используя вот такой типичный пример. Допустим у нас есть две таблицы:
Таблица users с полями id (pk int 11), name (varchar 255) Таблица posts с полями id (pk), title (varchar 255), user_id (int 11)
Мы хотим иметь возможность используя модель пользователей получить все записи пользователя, а используя модель постов получить автора поста. Соответственно делаем индекс для поля user_id, добавляем внешний ключ от этого поля к полю id таблицы users. Таким образом мы сможем получить автора поста через hasOne(), но можем ли мы не добавляя еще один внешний ключ получить через hasMany() все посты определенного автора?
Будет здорово, если кто-нибудь объяснит зачем нужно индексировать связующее поле перед добавлением к нему внешнего ключа.
Привожу пример кода как я все это пытаюсь делать.
$this->createIndex('user_id_index', 'posts', 'user_id');
тут я добавляю индекс для поля users_id и называю его user_id_index (кстати очень интересно зачем назвать индексы, как это делать правильно и где потом это имя использовать)
$this->addForeignKey('FK_posts_user_id', 'posts', 'user_id', 'users', 'id');
Тут я добавляю внешний ключ для таблицы posts для поля user_id, которое будет ссылаться на поле id таблицы users и называться FK_posts_user_id. Кстати буду очень признателен если меня поправят, если я что-то делается не так, как я описываю.
По итогу мы получаем внешний ключ и можем получить пользователя из модели с постами через вот такой геттер
public function getUsers() { $this->hasOne(Users::className(), ['id'=> 'user_id']); }
Соответственно чтобы получить все посты пользователя я модели пользователей делаю такого плана геттер:
public function getPosts() { $this->hasMany(Posts::className(), ['user_id', 'id']); }
Теперь подытожим вопросы:
Правильно ли я делаю? Правильный ли ход мысли? Нужно ли еще добавлять внешний ключ для таблицы пользователей (id,который ссылается на поле user_id в таблице posts)? Для чего нужно называть индексы и где потом эти названия используются? Где используются названия внешних ключей и для чего они нужны?
Буду очень благодарен за разъяснения и советы.


Ответ

Спустя некоторое время копания кода, доков и различных эксперементов с моделями и внешними ключами могу сделать заключение и ответить на свой собственный вопрос. Возможно это кому-нибудь пригодится.
В представленном мною коде есть ошибка. haseOne() и hasMany() должны возвращать результат выполнения их же. Так что проверяйте есть ли return в вашем методе. В базе данных однозначно достаточно только одного внешнего ключа (в моем примере таблица posts) и одного индекса (для связующего поля, в моем примере поле user_id таблицы posts). Все это можно реализовать через миграции, что вполне удобно. В коде модели, как я уже писал, достаточно написать метод haseOne() для модели с постами (в контроллере например можно будет юзать такую конструкцию чтобы получить данные об авторе поста $model->user; Соответственно ваш метод в модели должен назваться getUser() ) Для получения всех постов автора делаем тоже самое, но с моделью юзеров и описываем метод getPost() (назвать можете как хотите, только не забудьте про get в начале), внутри него возвращаем hasMany(). Точно так же можно получить все посты пользователя если заюзать $model->post;
p.s. Если у кого-то не выходит создать внешний ключ и валится ошибка вида Cannot add foreign key constraint - проверьте чтобы данные первичного ключа (id) и связующего поля (user_id) были идентичны. Если у юзера в поле id стоит NOTNULL - то и у связующего поля тоже он должен стоять, так же должен быть выбран одинаковый тип данный у полей (например и там и там INT(11).
Для моего примера приведу рабочий код для миграции, который вам создаст индекс и внешний ключ, необходимый для работы. Чуть поменяете под себя (измените названия полей и таблицы исходя из моего примера в вопросе и вуаля!)
$this->createIndex('user_id_index', 'posts', 'user_id'); $this->addForeignKey('FK_posts_user_id', 'posts', 'user_id', 'users', 'id', CASCADE', 'CASCADE');