Is it possible to design Cloud Firestore database to retrieve objects which have objects inside themselves? I have one object which has 5 other objects inside and I would like to retrieve it from this database. If it is possible, how can I do it?
data class Article(var objectId: String? = null,
var objectType: Int? = null,
var typeOfScaling: Int? = null,
var title: String? = null,
var header: Header? = null,
var source: Source? = null,
var listOfRelatedArticlesIds: List<String>? = null,
var listOfParagraphs: List<Paragraph>? = null,
var listOfPhotos: List<Photo>? = null,
var tour: Tour? = null): Serializable
data class Header(var title: String? = null,
var content: List<Pair<String, String>>? = null): Serializable
data class Source(var srcDescription: String? = null,
var photoId: String? = "Z1_0",
var url: String? = null,
var page: String? = null): Serializable
...
Thanks in advance.
Related
I'm using Github's search API in Android App through retrofit
https://api.github.com/search/users?q=user
The API Service file states as :
interface ApiService {
#GET("search/users")
suspend fun getUsers(#Query ("q") searchQuery: String)
: UserResponse
}
Meanwhile, the data class is :
data class UserResponse(
val total_count: Int,
val incomplete_results: Boolean,
val items: MutableList<Item>
){
data class Item( val avatar_url: String,
val events_url: String,
val followers_url: String,
val following_url: String,
val gists_url: String,
val gravatar_id: String,
val html_url: String,
val id: Int,
val login: String,
val node_id: String,
val organizations_url: String,
val received_events_url: String,
val repos_url: String,
val site_admin: Boolean,
val starred_url: String,
val subscriptions_url: String,
val type: String,
val url: String)
}
But, I'm having an error
FATAL EXCEPTION: DefaultDispatcher-worker-2
Process: com.example.github, PID: 3542
retrofit2.HttpException: HTTP 422
I tried change #Query param but it's not working
data class Class1 (
#SerializedName("total_count")
var totalCount: Int? = null,
#SerializedName("incomplete_results")
var incompleteResults : Boolean?= null,
#SerializedName("items") var items: ArrayList<Items> = arrayListOf()
)
data class Items (
#SerializedName("login")
var login: String? = null,
#SerializedName("id")
var id: Int? = null,
#SerializedName("node_id")
var nodeId: String? = null,
#SerializedName("avatar_url")
var avatarUrl: String? = null,
#SerializedName("gravatar_id")
var gravatarId: String? = null,
#SerializedName("url")
var url: String? = null,
#SerializedName("html_url")
var htmlUrl: String? = null,
#SerializedName("followers_url")
var followersUrl : String? = null,
#SerializedName("following_url")
var followingUrl : String? = null,
#SerializedName("gists_url")
var gistsUrl : String? = null,
#SerializedName("starred_url")
var starredUrl: String? = null,
#SerializedName("subscriptions_url")
var subscriptionsUrl : String? = null,
#SerializedName("organizations_url")
var organizationsUrl : String? = null,
#SerializedName("repos_url")
var reposUrl: String? = null,
#SerializedName("events_url")
var eventsUrl : String? = null,
#SerializedName("received_events_url" )
var receivedEventsUrl : String? = null,
#SerializedName("type")
var type : String? = null,
#SerializedName("site_admin")
var siteAdmin : Boolean? = null,
#SerializedName("score")
var score: Int? = null
)
I am trying to get a specific value from my JSON data. I could successfully call the entire json data,jsonOutput. But the thing is when I call a specific value in the jsonOutput, it shows me nullPointerError. I do not know why I lost the data when I call my data class. I marked the part I lost them with The problem occurs here. How can I get adminArea1?
I shared one data class as a sample. You can create the data classes with "Kotlin data class File from JSON".
I referred to many answers and examples but was hard to know the reason.
My code
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
binding.networkBtn.setOnClickListener(View.OnClickListener {
var thread = NetworkThread()
thread.start()
})
}
inner class NetworkThread : Thread() {
override fun run() {
var url =
URL("https://www.mapquestapi.com/geocoding/v1/reverse?key=LBK8QWxDPYHfmeYVlEP1IO3BVbWHyznB&" +
"location=Your_laptitue,Your_longitute&includeRoadMetadata=true&includeNearestIntersection=true")
var countryCodeBufferedReader =
BufferedReader(InputStreamReader(url.openConnection().getInputStream()))
var stringBuffer = StringBuffer()
do {
var string = countryCodeBufferedReader.readLine()
if (string != null) {
stringBuffer.append(string)
}
} while (string != null)
var jsonObject = JSONObject(stringBuffer.toString())
val gson: Gson = GsonBuilder().setPrettyPrinting().create()
val jsonOutput: String = gson.toJson(jsonObject)
//The problem occurs here
var countryData = gson.fromJson(jsonOutput, NameValuePairsXXXXX::class.java)
val jsonOutput2 = countryData.adminArea1
Log.d("jsonOutput", jsonOutput)
Log.d("jsonOutput2", jsonOutput2)
runOnUiThread {
binding.lapLonText.text = jsonOutput2
}
}
}
}
Data class
Use this class and use Response data class to parse json,
data class Response(
val options: Options? = null,
val results: List<ResultsItem?>? = null,
val info: Info? = null
)
data class Options(
val thumbMaps: Boolean? = null,
val maxResults: Int? = null,
val ignoreLatLngInput: Boolean? = null
)
data class LatLng(
val lng: Double? = null,
val lat: Double? = null
)
data class Info(
val statuscode: Int? = null,
val copyright: Copyright? = null,
val messages: List<Any?>? = null
)
data class ProvidedLocation(
val latLng: LatLng? = null
)
data class Copyright(
val imageAltText: String? = null,
val imageUrl: String? = null,
val text: String? = null
)
data class DisplayLatLng(
val lng: Double? = null,
val lat: Double? = null
)
data class LocationsItem(
val dragPoint: Boolean? = null,
val displayLatLng: DisplayLatLng? = null,
val adminArea4: String? = null,
val unknownInput: String? = null,
val adminArea5: String? = null,
val adminArea6: String? = null,
val postalCode: String? = null,
val adminArea1: String? = null,
val adminArea3: String? = null,
val sideOfStreet: String? = null,
val type: String? = null,
val adminArea6Type: String? = null,
val geocodeQualityCode: String? = null,
val adminArea4Type: String? = null,
val linkId: String? = null,
val roadMetadata: Any? = null,
val street: String? = null,
val nearestIntersection: Any? = null,
val adminArea5Type: String? = null,
val mapUrl: String? = null,
val geocodeQuality: String? = null,
val adminArea1Type: String? = null,
val adminArea3Type: String? = null,
val latLng: LatLng? = null
)
data class ResultsItem(
val locations: List<LocationsItem?>? = null,
val providedLocation: ProvidedLocation? = null
)
var countryData = gson.fromJson(jsonOutput, Reponse::class.java)
It was caused due to API communication. I solved my problem by putting okHttpClient. I added the code to help anybody having the same question.
val client = OkHttpClient()
val request = Request.Builder().url(url).build()
client.newCall(request).enqueue(object :Callback{
override fun onFailure(call: Call, e: IOException) {
Log.d("fail", "fail")
}
override fun onResponse(call: Call, response: okhttp3.Response) {
var body = response.body?.string()
Log.d("body", "$body")
val jsonObject2 : JSONObject = JSONObject(body.toString())
val jsonOutput2 = gson.fromJson(body, Response::class.java)
val test2 = jsonOutput2.results?.get(0)?.locations?.get(0)?.adminArea1.toString()
Log.d("test2", test2) }}
So I'm trying to fetch an API with endpoint https://someURL.com/switching-product/switch?orderID=A001,
This is the returned JSON format as seen from Postman.
So I use this Interface in the NetworkConfig.kt class to fetch this endpoint:
//Endpoint: https://someURL.com/switching-product/switch?orderID=A001
interface getOutstandingOrderDetail{
#GET("switch")
fun getOutstandingOrderDetail(#Query("orderID") orderID: String): Call<OutstandingOrderDetailPOJODataClassData>
}
and store it in this data class (Generated by an Android Extension that generate POJO from JSON):
data class OutstandingOrderDetailPOJODataClass(
#field:SerializedName("data")
val data: OutstandingOrderDetailPOJODataClassData? = null,
#field:SerializedName("error")
val error: Error? = null
)
data class OutstandingOrderDetailPOJODataClassData(
#field:SerializedName("Header")
val header: OutstandingOrderDetailPOJODataClassHeader? = null,
#field:SerializedName("Detail")
val detail: List<OutstandingOrderDetailPOJODataClassDetailItem?>? = null
)
data class OutstandingOrderDetailPOJODataClassHeader(
#field:SerializedName("buyer_address")
val buyerAddress: String? = null,
#field:SerializedName("total_price")
val totalPrice: Int? = null,
#field:SerializedName("buyer_name")
val buyerName: String? = null,
#field:SerializedName("status_confirmed_yn")
val statusConfirmedYn: String? = null,
#field:SerializedName("order_date")
val orderDate: String? = null,
#field:SerializedName("outlet_id")
val outletId: String? = null,
#field:SerializedName("nip")
val nip: String? = null,
#field:SerializedName("jumlah_product")
val jumlahProduct: Int? = null,
#field:SerializedName("last_update")
val lastUpdate: String? = null,
#field:SerializedName("phone_number")
val phoneNumber: String? = null,
#field:SerializedName("order_running_id")
val orderRunningId: Int? = null,
#field:SerializedName("status_tagged_yn")
val statusTaggedYn: String? = null,
#field:SerializedName("order_id")
val orderId: String? = null
)
data class OutstandingOrderDetailPOJODataClassError(
#field:SerializedName("msg")
val msg: String? = null,
#field:SerializedName("code")
val code: Int? = null,
#field:SerializedName("status")
val status: Boolean? = null
)
data class OutstandingOrderDetailPOJODataClassDetailItem(
#field:SerializedName("item_price_new")
val itemPriceNew: Int? = null,
#field:SerializedName("item_name_new")
val itemNameNew: String? = null,
#field:SerializedName("total_price")
val totalPrice: Int? = null,
#field:SerializedName("item_price")
val itemPrice: Int? = null,
#field:SerializedName("item_name")
val itemName: String? = null,
#field:SerializedName("status_refund")
val statusRefund: String? = null,
#field:SerializedName("detail_id")
val detailId: Int? = null,
#field:SerializedName("procode_new")
val procodeNew: String? = null,
#field:SerializedName("refund_date")
val refundDate: String? = null,
#field:SerializedName("request_refund")
val requestRefund: String? = null,
#field:SerializedName("procode")
val procode: String? = null,
#field:SerializedName("last_update")
val lastUpdate: String? = null,
#field:SerializedName("item_qty_new")
val itemQtyNew: Int? = null,
#field:SerializedName("order_id")
val orderId: String? = null,
#field:SerializedName("total_price_new")
val totalPriceNew: Int? = null,
#field:SerializedName("item_qty")
val itemQty: Int? = null,
#field:SerializedName("refund")
val refund: Int? = null
)
This is a code snippet of the fragment where I fetch the URL data:
private fun fetchOrderedItemListData() {
NetworkConfig()
.getOutstandingDetailOrderedItemListService()
.getOutstandingOrderDetailOrderedItemList("A001")
.enqueue(object :
Callback<OutstandingOrderDetailPOJODataClassData> {
override fun onFailure(
call: Call<OutstandingOrderDetailPOJODataClassData>,
t: Throwable
) {
Log.i("Order", "It Failed!!")
if (call.isCanceled) {
Toast.makeText(
(activity as AppCompatActivity),
"Request Aborted",
Toast.LENGTH_SHORT
).show()
} else {
Toast.makeText(
(activity as AppCompatActivity),
t.localizedMessage,
Toast.LENGTH_SHORT
).show()
}
}
override fun onResponse(
call: Call<OutstandingOrderDetailPOJODataClassData>,
response: Response<OutstandingOrderDetailPOJODataClassData>
) {
Log.i("Order", "Ordered Item FEtched -> \n ${response.body()}") <= This is for debugging purpose
binding.rvOrderedItemList.adapter =
response.body()
?.let { OrderedItemListAdapter(it, this#OrderDetailFragment) }
binding.rvOrderedItemList.layoutManager =
LinearLayoutManager((activity as AppCompatActivity))
}
})
}
As you can see above I use Log.i to try to print the response.body() in the LogCat, However it returns null in the Log Cat. You can see it here.
Am I missing something ? If there's any detail that I left out for this question, feel free to ask.
Your Retrofit function is set up as:
#GET("switch")
fun getOutstandingOrderDetail(#Query("orderID") orderID: String): Call<OutstandingOrderDetailPOJODataClassData>
The data type in the Call<> needs to match your JSON. You have data classes that match your JSON... but the root of that hierarchy is OutstandingOrderDetailPOJODataClass, not OutstandingOrderDetailPOJODataClassData. So, change your Retrofit function to:
#GET("switch")
fun getOutstandingOrderDetail(#Query("orderID") orderID: String): Call<OutstandingOrderDetailPOJODataClass>
I have the following models:
Cart object
open class Cart(
#PrimaryKey
var id: String? = null,
var orders: RealmList<Deal> = RealmList()
) : RealmObject()
Deal object
open class Deal(
#field:SerializedName("short_description")
var shortDescription: String? = null,
#field:SerializedName("original_price")
var originalPrice: Int? = null,
#field:SerializedName("deal_category")
var dealCategory: DealCategory? = null,
#field:SerializedName("images")
var images: RealmList<Image>? = null,
#field:SerializedName("featured")
var featured: String? = null,
#field:SerializedName("deal_type")
var dealType: DealType? = null,
#field:SerializedName("deal_of_day")
var dealOfDay: String? = null,
#field:SerializedName("restaurant")
var restaurant: Restaurant? = null,
#field:SerializedName("expiry_date")
var expiryDate: String? = null,
#field:SerializedName("description")
var description: String? = null,
#field:SerializedName("page_views")
var pageViews: Int? = null,
#field:SerializedName("price")
var price: Int? = null,
#field:SerializedName("name")
var name: String? = null,
#field:SerializedName("alias")
var alias: String? = null,
#field:SerializedName("links")
var links: RealmList<Link>? = null,
#field:SerializedName("id")
var id: Int? = null,
#field:SerializedName("user")
var user: User? = null,
#field:SerializedName("status")
var status: String? = null
): RealmObject()
Restaurant object
open class Restaurant(
#field:SerializedName("location_address")
var locationAddress: String? = null,
#field:SerializedName("website")
var website: String? = null,
#field:SerializedName("featured")
var featured: String? = null,
#field:SerializedName("latitude")
var latitude: String? = null,
#field:SerializedName("opening_time")
var openingTime: String? = null,
#field:SerializedName("description")
var description: String? = null,
#field:SerializedName("created_at")
var createdAt: String? = null,
#field:SerializedName("updated_at")
var updatedAt: String? = null,
#field:SerializedName("phone")
var phone: String? = null,
#field:SerializedName("closing_time")
var closingTime: String? = null,
#field:SerializedName("name")
var name: String? = null,
#field:SerializedName("preparation_time")
var preparationTime: Int? = null,
#field:SerializedName("alias")
var alias: String? = null,
#PrimaryKey
#field:SerializedName("id")
var id: Int? = null,
#field:SerializedName("ideal_class")
var idealClass: String? = null,
#field:SerializedName("email")
var email: String? = null,
#field:SerializedName("status")
var status: String? = null,
#field:SerializedName("longitude")
var longitude: String? = null
) : RealmObject()
When I initially add deals to the cart, everything functions ok but when I add a deal to the cart that has an already existing restaurant entry present, I get the RealmPrimaryKeyConstraintException. My method is as below:
Realm.getInstance(RealmUtil.realmConfiguration).use {realm ->
var cart = realm.where<Cart>().findFirst()
realm.executeTransaction {
if (cart == null) {
cart = Cart().apply {
id = getString(R.string.app_name)
orders.add(deal)
}
} else {
cart!!.orders.add(deal)
}
it.copyToRealmOrUpdate(cart!!)
invalidateOptionsMenu()
}
}
The error I get is:
io.realm.exceptions.RealmPrimaryKeyConstraintException: Primary key value already exists: 43 .
(/Users/cm/Realm/realm-java/realm/realm-library/src/main/cpp/io_realm_internal_OsObject.cpp:197)
at io.realm.internal.OsObject.nativeCreateNewObjectWithLongPrimaryKey(Native Method)
at io.realm.internal.OsObject.createWithPrimaryKey(OsObject.java:208)
at io.realm.Realm.createObjectInternal(Realm.java:996)
at io.realm.com_deals_bakooli_model_RestaurantRealmProxy.copy(com_deals_bakooli_model_RestaurantRealmProxy.java:1072)
at io.realm.com_deals_bakooli_model_RestaurantRealmProxy.copyOrUpdate(com_deals_bakooli_model_RestaurantRealmProxy.java:1062)
at io.realm.com_deals_bakooli_model_DealRealmProxy.copy(com_deals_bakooli_model_DealRealmProxy.java:1250)
at io.realm.com_deals_bakooli_model_DealRealmProxy.copyOrUpdate(com_deals_bakooli_model_DealRealmProxy.java:1181)
at io.realm.DefaultRealmModuleMediator.copyOrUpdate(DefaultRealmModuleMediator.java:214)
at io.realm.Realm.copyOrUpdate(Realm.java:1634)
at io.realm.Realm.copyToRealm(Realm.java:1016)
at io.realm.RealmModelListOperator.copyToRealmIfNeeded(RealmList.java:1530)
at io.realm.RealmModelListOperator.appendValue(RealmList.java:1456)
at io.realm.ManagedListOperator.append(RealmList.java:1337)
at io.realm.RealmList.add(RealmList.java:210)
at com.deals.bakooli.activity.SingleDealActivity$addItemToCart$$inlined$use$lambda$1.execute(SingleDealActivity.kt:102)
at io.realm.Realm.executeTransaction(Realm.java:1431)
at com.deals.bakooli.activity.SingleDealActivity.addItemToCart(SingleDealActivity.kt:91)
at com.deals.bakooli.activity.SingleDealActivity.onClick(SingleDealActivity.kt:82)
I don't understand why despite using copyToRealmOrUpdate, the exception is thrown. What am I doing wrong?
Your query looks incorrect.
Try
realm.where(Cart.class).findFirst()
I have a Room Query , which returns few fields of the POJO. Eg. query returns group_id, group_name only But the POJO have more fields like
sender_name, message etc. If I compile the code it gives me an error. I see my build getting failed, But no error related to ROOM.
I want to know can I have more fields in POJO than what the query returns. Because if I keep only group_Id and group_name in POJO, compilation succeeds.
#Query("SELECT group_id,group_name FROM group")
fun getGroups(): DataSource.Factory<Int, Chat>
class Chat {
#ColumnInfo(name = "group_id")
var groupId: String = ""
#ColumnInfo(name = "group_name")
var groupName: String? = null
var sender: String? = null
#ColumnInfo(name = "created_by")
var createdBy: String? = null
#ColumnInfo(name = "message_id")
var messageId: String? = null
#ColumnInfo(name = "message")
var text: String? = null
}
You need to annotate your POJO class as (Optional),
#Entity(tableName = "group")
class Chat {
#ColumnInfo(name = "group_id")
var groupId: String = ""
#ColumnInfo(name = "group_name")
var groupName: String? = null
var sender: String? = null
#ColumnInfo(name = "created_by")
var createdBy: String? = null
#ColumnInfo(name = "message_id")
var messageId: String? = null
#ColumnInfo(name = "message")
var text: String? = null
}
and change your return type as,
#Query("SELECT group_id,group_name FROM group")
fun getGroups(): List<Chat>
(this might remove your compilation error).