Dynamic Dependencies off a multiple choice list? - react-jsonschema-forms

Suppose you had a JSON form schema like this:
{
"type": "object",
"properties": {
"food_eaten": {
"type": "array",
"title": "What kinds of food did you eat today?",
"items": {
"type": "string",
"enum": [
"Fruits",
"Meats",
"Veggies",
"Pastries"
]
},
"uniqueItems": true
},
"fruit_eaten":{
"title": "What kind of fruit did you eat?",
"type": "string"
},
"meats_eaten":{
"title": "What kind of meats did you eat?",
"type": "string"
},
"veggies_eaten":{
"title": "What kind of veggies did you eat?",
"type": "string"
},
"pastries_eaten":{
"title": "What kind of pastries did you eat?",
"type": "string"
}
}
}
And you wanted to make it so that when a user answers the "foods_eaten" question, only the relevant "x_eaten" questions appear. E.G. if the user selects "Meats" and "Veggies" under "food_eaten", then only "meats_eaten" and "veggies_eaten" would display.
I've done every variation of schema and property dependencies I can think of, tried using oneOf and anyOf, but nothing seems to work. I'd really appreciate some pointers!

One of the solutions mentioned in react-jsonschema-form's GitHub was to use oneOf with every combination of selections listed out.
For your case that would look something like (Code Sandbox):
{
type: "object",
properties: {
food_eaten: {
title: "What kinds of food did you eat today?",
type: "array",
uniqueItems: true,
items: {
type: "string",
enum: ["Fruits", "Meats", "Veggies", "Pastries"]
}
}
},
dependencies: {
food_eaten: {
oneOf: [
{
properties: {
food_eaten: {
const: ["Fruits"]
},
fruit_eaten: {
type: "string",
title: "What kind of fruit did you eat?"
}
}
},
{
properties: {
food_eaten: {
const: ["Meats"]
},
meats_eaten: {
type: "string",
title: "What kind of meat did you eat?"
}
}
},
{
properties: {
food_eaten: {
const: ["Veggies"]
},
veggies_eaten: {
type: "string",
title: "What kind of veggies did you eat?"
}
}
},
{
properties: {
food_eaten: {
const: ["Pastries"]
},
pastries_eaten: {
type: "string",
title: "What kind of pastries did you eat?"
}
}
},
{
properties: {
food_eaten: {
const: ["Fruits", "Meats"]
},
fruit_eaten: {
type: "string",
title: "What kind of fruit did you eat?"
},
meats_eaten: {
type: "string",
title: "What kind of meat did you eat?"
}
}
},
{
properties: {
food_eaten: {
const: ["Fruits", "Veggies"]
},
fruit_eaten: {
type: "string",
title: "What kind of fruit did you eat?"
},
veggies_eaten: {
type: "string",
title: "What kind of veggies did you eat?"
}
}
},
{
properties: {
food_eaten: {
const: ["Fruits", "Pastries"]
},
fruit_eaten: {
type: "string",
title: "What kind of fruit did you eat?"
},
pastries_eaten: {
type: "string",
title: "What kind of pastries did you eat?"
}
}
},
{
properties: {
food_eaten: {
const: ["Meats", "Veggies"]
},
meats_eaten: {
type: "string",
title: "What kind of meats did you eat?"
},
veggies_eaten: {
type: "string",
title: "What kind of veggies did you eat?"
}
}
},
{
properties: {
food_eaten: {
const: ["Meats", "Pastries"]
},
meats_eaten: {
type: "string",
title: "What kind of meats did you eat?"
},
pastries_eaten: {
type: "string",
title: "What kind of pastries did you eat?"
}
}
},
{
properties: {
food_eaten: {
const: ["Veggies", "Pastries"]
},
veggies_eaten: {
type: "string",
title: "What kind of veggies did you eat?"
},
pastries_eaten: {
type: "string",
title: "What kind of pastries did you eat?"
}
}
},
{
properties: {
food_eaten: {
const: ["Fruits", "Meats", "Veggies"]
},
fruit_eaten: {
type: "string",
title: "What kind of fruits did you eat?"
},
meats_eaten: {
type: "string",
title: "What kind of meats did you eat?"
},
veggies_eaten: {
type: "string",
title: "What kind of veggies did you eat?"
}
}
},
{
properties: {
food_eaten: {
const: ["Fruits", "Meats", "Pastries"]
},
fruit_eaten: {
type: "string",
title: "What kind of fruits did you eat?"
},
meats_eaten: {
type: "string",
title: "What kind of meats did you eat?"
},
pastries_eaten: {
type: "string",
title: "What kind of pastries did you eat?"
}
}
},
{
properties: {
food_eaten: {
const: ["Meats", "Veggies", "Pastries"]
},
meats_eaten: {
type: "string",
title: "What kind of meats did you eat?"
},
veggies_eaten: {
type: "string",
title: "What kind of veggies did you eat?"
},
pastries_eaten: {
type: "string",
title: "What kind of pastries did you eat?"
}
}
},
{
properties: {
food_eaten: {
const: ["Fruits", "Veggies", "Pastries"]
},
fruits_eaten: {
type: "string",
title: "What kind of fruits did you eat?"
},
veggies_eaten: {
type: "string",
title: "What kind of veggies did you eat?"
},
pastries_eaten: {
type: "string",
title: "What kind of pastries did you eat?"
}
}
},
{
properties: {
food_eaten: {
const: ["Fruits", "Meats", "Veggies", "Pastries"]
},
meats_eaten: {
type: "string",
title: "What kind of meats did you eat?"
},
fruits_eaten: {
type: "string",
title: "What kind of fruits did you eat?"
},
veggies_eaten: {
type: "string",
title: "What kind of veggies did you eat?"
},
pastries_eaten: {
type: "string",
title: "What kind of pastries did you eat?"
}
}
}
]
}
}
}
They do mention that the solution might become simpler after allOf gets implemented (which it is now) so perhaps you might be able to simplify this approach. I would recommend joining the RJSF discord and ask about it there, you may get some advice.

Related

Google Chat API: How do I switch between Cards v1 and Cards v2?

According to the docs, Cards v1 is deprecated, and Cards v2 seems to be much more feature-rich.
But when I use the Cards v2 syntax, the API complains about unknown or missing fields. How can I tell the Google servers that I want to use the v2 API? The documentation does not seem to tell anything about that.
All tutorials that I can find seem to use Cards v1 only. I'm mostly following the official tutorial in Python.
I tried to send message with card v2 with this syntax:
"cards_v2": [[{
"card_id": "addContact",
"card": {}
}]
Request:
POST https://chat.googleapis.com/v1/spaces/space_name/messages
{
"cards_v2": [{
"card_id": "addContact",
"card": {
"header": {
"title": "Rolodex",
"subtitle": "Manage your contacts!",
"imageUrl": "https://www.gstatic.com/images/branding/product/2x/contacts_48dp.png",
"imageType": "CIRCLE"
},
"sections": [
{
"widgets": [
{
"buttonList": {
"buttons": [
{
"text": "Add Contact",
"onClick": {
"action": {
"function": "openDialog",
"interaction": "OPEN_DIALOG"
}
}
}
]
},
"horizontalAlignment": "CENTER"
}
]
}
]
}
}]
,
"thread": {
"name": "spaces/space_name/threads/thread_name"
}
}
Taken from here:
https://developers.google.com/chat/how-tos/dialogs?hl=en
Use the following JSON schema to use v2 cards;
{
"cardsV2": [
{
"cardId": "unique-card-id",
"card": {
"header": {
"title": "Sasha",
"subtitle": "Software Engineer",
"imageUrl":
"https://developers.google.com/chat/images/quickstart-app-avatar.png",
"imageType": "CIRCLE",
"imageAltText": "Avatar for Sasha",
},
"sections": [
{
"header": "Contact Info",
"collapsible": true,
"uncollapsibleWidgetsCount": 1,
"widgets": [
{
"decoratedText": {
"startIcon": {
"knownIcon": "EMAIL",
},
"text": "sasha#example.com",
}
},
{
"decoratedText": {
"startIcon": {
"knownIcon": "PERSON",
},
"text": "<font color=\"#80e27e\">Online</font>",
},
},
{
"decoratedText": {
"startIcon": {
"knownIcon": "PHONE",
},
"text": "+1 (555) 555-1234",
}
},
{
"buttonList": {
"buttons": [
{
"text": "Share",
"onClick": {
"openLink": {
"url": "https://example.com/share",
}
}
},
{
"text": "Edit",
"onClick": {
"action": {
"function": "goToView",
"parameters": [
{
"key": "viewType",
"value": "EDIT",
}
],
}
}
},
],
}
},
],
},
],
},
}
],
}
visit Google chat docs for more

How can I create a Pydantic Model for my FastAPI endpoint when my JSON is something like this?

{
'events': [
{
'type': 'message',
'replyToken': '0bc647fc5282423cde13fffbc947a8',
'source': {
'userId': 'U996ed69353d3c962ee17b33d9af3e2',
'type': 'user'
},
'timestamp': 161185209914,
'mode': 'active',
'message': {
'type': 'text',
'id': '1346188304367',
'text': ' hello'
}
}
],
'destination': 'Uf44eb3ba6c4b87adbfaa4a517e'
}
this is the json from the webhook I'm using
it's contained like this, how can I write a Pytantic model for it?
This should work fine with the request body you given above.
from pydantic import BaseModel
from typing import List
class Source(BaseModel):
userId: str
type: str
class Message(BaseModel):
type: str
id: str
text: str
class Event(BaseModel):
type: str
replyToken: str
source: Source
timestamp: int
mode: str
message: Message
class Webhook(BaseModel):
events: List[Event]
destination: str
Here is the OpenAPI schema for Webhook model.
{
"title": "Webhook",
"type": "object",
"properties": {
"events": {
"title": "Events",
"type": "array",
"items": {
"$ref": "#/definitions/Event"
}
},
"destination": {
"title": "Destination",
"type": "string"
}
},
"required": [
"events",
"destination"
],
"definitions": {
"Source": {
"title": "Source",
"type": "object",
"properties": {
"userId": {
"title": "Userid",
"type": "string"
},
"type": {
"title": "Type",
"type": "string"
}
},
"required": [
"userId",
"type"
]
},
"Message": {
"title": "Message",
"type": "object",
"properties": {
"type": {
"title": "Type",
"type": "string"
},
"id": {
"title": "Id",
"type": "string"
},
"text": {
"title": "Text",
"type": "string"
}
},
"required": [
"type",
"id",
"text"
]
},
"Event": {
"title": "Event",
"type": "object",
"properties": {
"type": {
"title": "Type",
"type": "string"
},
"replyToken": {
"title": "Replytoken",
"type": "string"
},
"source": {
"$ref": "#/definitions/Source"
},
"timestamp": {
"title": "Timestamp",
"type": "integer"
},
"mode": {
"title": "Mode",
"type": "string"
},
"message": {
"$ref": "#/definitions/Message"
}
},
"required": [
"type",
"replyToken",
"source",
"timestamp",
"mode",
"message"
]
}
}
}

How to get rid of "API must not have local definitions (i.e. only $refs are allowed)" Swaggerhub standardization error with Springfox

I have swagger api-docs.json definition generated by SpringFox.
Below minimal-reproducible-example:
{
"swagger": "2.0",
"info": {
"description": "Example REST API.",
"version": "15.11.02",
"title": "Example REST API",
"contact": {
"name": "ExampleTeam",
"url": "https://example.com/",
"email": "support#example.com"
},
"license": {
"name": "Apache License 2.0",
"url": "https://www.apache.org/licenses/LICENSE-2.0.txt"
}
},
"host": "d01088db.ngrok.io",
"basePath": "/cloud",
"tags": [
{
"name": "All Endpoints",
"description": " "
}
],
"paths": {
"/api/v2/users/{userId}/jobs/{jobId}": {
"get": {
"tags": [
"Builds",
"All Endpoints"
],
"summary": "Get job.",
"operationId": "getJobUsingGET",
"produces": [
"*/*"
],
"parameters": [
{
"name": "jobId",
"in": "path",
"description": "jobId",
"required": true,
"type": "integer",
"format": "int64"
},
{
"name": "userId",
"in": "path",
"description": "userId",
"required": true,
"type": "integer",
"format": "int64"
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/APIPipelineJob"
}
},
"401": {
"description": "Unauthorized"
},
"403": {
"description": "Forbidden"
},
"404": {
"description": "Not Found"
}
},
"deprecated": false
}
}
},
"definitions": {
"APIPipelineJob": {
"type": "object",
"properties": {
"archiveTime": {
"type": "string",
"format": "date-time",
"example": "example"
},
"content": {
"type": "string",
"example": "example"
},
"createTime": {
"type": "string",
"format": "date-time",
"example": "example"
},
"id": {
"type": "integer",
"format": "int64",
"example": "example"
},
"name": {
"type": "string",
"example": "example"
},
"selfURI": {
"type": "string",
"example": "example"
},
"type": {
"type": "string",
"example": "example",
"enum": [
"BUILD",
"DEPLOY"
]
},
"userId": {
"type": "integer",
"format": "int64",
"example": "example"
}
},
"title": "APIPipelineJob",
"xml": {
"name": "APIPipelineJob",
"attribute": false,
"wrapped": false
}
}
}
}
When I import it to SwaggerHub I got standardization error:
'definitions.*' not allowed -> API must not have local definitions (i.e. only $refs are allowed)
I have found the recommended solution in SwaggerHub documentation
But here is my question how to achieve:
split into domains(then using a reference), or
inline schemas
with Springfox
Or maybe there is another way to get rid of the above standardization error?
If you go to your home page, then hover over your organization on the left hand side and go to settings > Standardization, you should see some options. Unselect "API must not have local definitions (i.e. only $refs are allowed)" at the bottom.
And don't forget to save at the top right!

Decoding Nested JSON Elements (SwiftUI)

I am trying to parse the JSON data below into the structs that are shown. I am having a helluva time trying to figure out how to get at the "nested" elements, such as elements "title:", "content:", and "excerpt:". Whenever the code runs, it barfs while parsing the nested elements.
I've looked at the Apple Developer stuff and reviewed the Playground here: https://developer.apple.com/documentation/foundation/archives_and_serialization/using_json_with_custom_types
I also tried using quicktype.io to create the data models from the sample JSON, however, in the header of the exported file from quicktype it has the line: "let blogItem = try? newJSONDecoder().decode(BlogItem.self, from: jsonData)", however, I get a compile error that jsonData is not recognized and I'm not able to find any reference to it.
struct BlogSection: Codable, Identifiable {
var id: Int
var slug: String
var link: String
var title: [BlogTitle]
var content: [ContentData]
}
struct BlogTitle: Codable, Equatable, Identifiable {
var id: UUID
var rendered: String
}
struct ContentData: Codable, Identifiable{
var id: UUID
var rendered: String
}
/**************** JSON Data ***************/
[
{
"id": 10960,
"date": "2019-10-02T01:00:07",
"date_gmt": "2019-10-02T05:00:07",
"guid": {
"rendered": "example.com/blog-template-copy-copy/"
},
"modified": "2019-09-20T07:08:41",
"modified_gmt": "2019-09-20T11:08:41",
"slug": "relationships-matter",
"status": "publish",
"type": "post",
"link": "example.com/relationships-matter/",
"title": {
"rendered": "Relationships Matter"
},
"content": {
"rendered": "<h1>Page content</h1>",
"protected": false
},
"excerpt": {
"rendered": "<p>By: Joe Schmoe<br />\nFirst Author",
"protected": false
},
"author": 57,
"featured_media": 10958,
"comment_status": "open",
"ping_status": "open",
"sticky": false,
"template": "",
"format": "standard",
"meta": [],
"categories": [
613
],
"tags": [],
"_links": {
"self": [
{
"href": "example.com/wp-json/wp/v2/posts/10960"
}
],
"collection": [
{
"href": "example.com/wp-json/wp/v2/posts"
}
],
"about": [
{
"href": "example.com/wp-json/wp/v2/types/post"
}
],
"author": [
{
"embeddable": true,
"href": "example.com/wp-json/wp/v2/users/57"
}
],
"replies": [
{
"embeddable": true,
"href": "example.com/wp-json/wp/v2/comments?post=10960"
}
],
"version-history": [
{
"count": 5,
"href": "example.com/wp-json/wp/v2/posts/10960/revisions"
}
],
"predecessor-version": [
{
"id": 10971,
"href": "example.com/wp-json/wp/v2/posts/10960/revisions/10971"
}
],
"wp:featuredmedia": [
{
"embeddable": true,
"href": "example.com/wp-json/wp/v2/media/10958"
}
],
"wp:attachment": [
{
"href": "example.com/wp-json/wp/v2/media?parent=10960"
}
],
"wp:term": [
{
"taxonomy": "category",
"embeddable": true,
"href": "example.com/wp-json/wp/v2/categories?post=10960"
},
{
"taxonomy": "post_tag",
"embeddable": true,
"href": "example.com/wp-json/wp/v2/tags?post=10960"
}
],
"curies": [
{
"name": "wp",
"href": "https://api.w.org/{rel}",
"templated": true
}
]
}
}
]
'
In the JSON you do not have arrays for title and content, so just remove the brackets
struct BlogSection: Codable, Identifiable {
var id: Int
var slug: String
var link: String
var title: BlogTitle
var content: ContentData
}
struct BlogTitle: Codable, Equatable, Identifiable {
var id: UUID
var rendered: String
}
struct ContentData: Codable, Identifiable{
var id: UUID
var rendered: String
}
Title and Content are not Arrays in the json provided so should be declared as entities. Your BlogTitle and ContentData are declared as Identifiable and have a variable for id, but both do not have an id in the json provided, so you will get a decoding error because of that as well.
The error you are getting points to a completely different problem though. How is your jsonData declared?

Using Pact.eachLike() when array contents vary for each item

Hi I have a Consumer test produced using Pact NPM https://www.npmjs.com/package/pact
I use the following code to generate a pact.json:
provider
.addInteraction({
state: 'test',
uponReceiving: 'a test,
withRequest: {
method: 'GET',
path: '/test'
},
willRespondWith: {
status: 200,
headers: { 'Content-Type': 'application/json' }
body: {
"company": like("My big company"),
"factories": eachLike({
"location": like("Sydney"),
"capacity": like(5)
},{min:1})
}
}
})
.then(function(){ done(); });
It generates the following testconsumer-testprovider.json file:
{
"consumer": {
"name": "TestConsumer"
},
"provider": {
"name": "TestProvider"
},
"interactions": [
{
"description": "a request for loans",
"providerState": "broker is logged in, list all loans",
"request": {
"method": "GET",
"path": "/test"
},
"response": {
"status": 200,
"headers": {
"Content-Type": "application/vnd.hal+json"
},
"body": {
"company": "My big company",
"factories": [
{
"location": "Sydney",
"capacity": 5
}
]
},
"matchingRules": {
"$.headers.Content-Type": {
"match": "regex",
"regex": "application\\/.*json.*"
},
"$.body.company": {
"match": "type"
},
"$.body.factories": {
"min": 1
},
"$.body.factories[*].*": {
"match": "type"
},
"$.body.factories[*].location": {
"match": "type"
},
"$.body.factories[*].capacity": {
"match": "type"
}
}
}
}
],
"metadata": {
"pactSpecification": {
"version": "3.0.0"
}
}
}
However when we test against the following provided output we get an error with the geographicCoords because it's an unexpected key/value:
{
"company": "My Company",
"factories": [
{
"location": "Sydney",
"capacity": 5
},
{
"location": "Sydney",
"geographicCoords": "-0.145,1.4445",
"capacity": 5,
}
]
}
So is there a was to allow unexpected key/values in arrays because we're only test for required key/values and we don't want out pact tests to fail in future when new values are added to our providers.
The scenario you are describing is supported, see https://github.com/pact-foundation/pact-js/tree/master/examples/e2e for an example.
If you were to remove, say the eligibility object and run the tests everything still works.
If you are still having troubles, please raise a defect on the pact-js repository and we'll get to the bottom of it.

Resources