i have default.json file with properties. Example,
{
"!name": "test",
"Commit": {
"!doc": "test",
"!type": "fn(connectionName: string, k: string) -> object"
"default": {
"!doc": "test",
"z": {
"!doc": "test"
},
"p": {
"!doc": "test"
}
}
}
In redactor
var t = 'string';
Commit.t.
and i need that autocomplete with 'default' properties appears after "t". So, if "Commit" dont have that property (in this case "t"), then properties 'z' and 'p' appear.
how i can did it?
thanks
Related
I am using the following dataweave function, and it does works.
%dw 2.0
import * from dw::core::Arrays
output application/json
var mysqlInvoices = [
{
"id": 1,
"owner": "Joseph"
},
{
"id": 2,
"owner": "Maria"
}
]
var sapInvoices = [
{
"number": 3,
"issuedBy": "XYZ"
},
{
"number": 4,
"issuedBy": "ABC"
}
]
---
leftJoin(mysqlInvoices, sapInvoices, (m) -> m.id, (s) -> s.number) map (item, index) ->
(item.l mapObject (sItem, sKey) ->
(if ((sKey) as String == "id") "identifier"
else if ((sKey) as String == "owner") "ownerName"
else (sKey)): sItem)
++
(if (item.r != null)
item.r mapObject (sItem, sKey) ->
(sKey): sItem
else
sapInvoices[0] mapObject
(sItem, sKey) -> (sKey): "")
However, I am thinking if I can improve this function at two points:
change the key conditions:
I dont think that is the best practice to check every key match an if condition to change it:
(if ((sKey) as String == "id") "identifier"
else if ((sKey) as String == "owner") "ownerName"
else (sKey)): sItem
Use the original object to map it as an empty string when the leftJoin do not match keys:
sapInvoices[0] mapObject (sItem, sKey) ->
(sKey): ""
I am uncomfortable with these two points, and I believe that there are ways to improve this code, I just dont know how.
If there is a very different way of doing the same task, I also appreciate that kind of suggestion.
Based on George's answer, you can remove pluck and match and directly combine left and right table. See below:
%dw 2.0
import * from dw::core::Arrays
output application/json
var mysqlInvoices = [
{
"id": 1,
"owner": "Joseph"
},
{
"id": 2,
"owner": "Maria"
}
]
var sapInvoices = [
{
"number": 3,
"issuedBy": "XYZ"
},
{
"number": 4,
"issuedBy": "ABC"
}
]
var fs2rn = {
id: "identifier",
owner: "ownerName"
}
var rightEmpty= {number:"",issuedBy:""}
---
leftJoin(
// Do the field renaming at the very begining
mysqlInvoices map ($ mapObject {(fs2rn[$$] default $$): $}),
sapInvoices,
(m) -> m.identifier,
(s) -> s.number
) map (item) -> item.l ++ (item.r default rightEmpty)
Give the following a try, if anything the code seems a bit simpler:
%dw 2.0
import * from dw::core::Arrays
output application/json
var mysqlInvoices = [
{
"id": 1,
"owner": "Joseph"
},
{
"id": 2,
"owner": "Maria"
}
]
var sapInvoices = [
{
"number": 3,
"issuedBy": "XYZ"
},
{
"number": 4,
"issuedBy": "ABC"
}
]
var fs2rn = {
id: "identifier",
owner: "ownerName"
}
var rightEmpty= {number:"",issuedBy:""}
---
leftJoin(
// Do the field renaming at the very begining
mysqlInvoices map ($ mapObject {(fs2rn[$$] default $$): $}),
sapInvoices,
(m) -> m.identifier,
(s) -> s.number
)
// Iterate over the results
// Get just the values, and colapse the objects into a single object
map (
{($ pluck $)}
)
// Iterate over the results and use pattern-matching to
//
map (
$ match {
// Check if you have an id but not a number fields
// In which case add the rightEmpty object
case o if (o.identifier? and not (o.number?)) -> o ++ rightEmpty
// Or give the object because you now have both an id and a number
else o -> o
}
)
The features and functions I used are:
Dynamic Elements, documentation
pluck, documentation
Pattern-matching using the match operator, documentation
If I was to give you an advice, it would be to better indent your code. Nonetheless, pretty good job!
Is it possible to create a struct with dynamic/arbitrary fields and values?
My app will receive request with JSON body:
{
"Details": {
"Id": “123”,
},
"Event": {
"Event": "Event",
},
“RequestValues”: [
{
“Name": "Name1",
"Value": "Val1"
},
{
"Name": "Name2",
"Value": 2
},
{
"Name": “Foo”,
"Value": true
}
]
}
This will be unmarshalled to my model 'Request':
type Request struct {
Details Details `json:"Details"`
Event Event `json:"Event"`
RequestValues []RequestValues `json:"RequestValues"`
}
type Details struct {
Id string `json:"Id"`
}
type Event struct {
Event string `json:"Event"`
}
type RequestValues struct {
Name string `json:"Name"`
Value string `json:"Value"`
}
I have to re-map model 'Request' to a new model 'Event' with arbitrary fields in "Values". After marshalling new re- mapped model 'Event' I should get this JSON output that corresponds to the request:
{
"Event": "Event"
"Values": {
“Id": "123", <= non arbitrary mapping from Request.Detail.Id
"Name1": "Val1", <= arbitrary
"Name2": 2, <= arbitrary
“Foo”: true <= arbitrary
}
}
Arbitrary values will be mapped from "RequestValues". Names of those fields should be the values of Request.RequestValues.Name and their values should be the values of Request.RequestValues.Value
Here is my 'Event' model:
type Event struct {
Event string `json:"Event"`
Values Values `json:"Values"`
}
type Values struct{
Id string `json:"Id"`
}
Firstly, here's a JSON-valid copy of your JSON:
{
"Details": {
"Id": "123"
},
"Event": {
"Event": "Event"
},
"RequestValues": [
{
"RequestValueName": "Name1",
"RequestValue": "Val1"
},
{
"RequestValueName": "Name2",
"RequestValue": 2
},
{
"RequestValueName": "Foo",
"RequestValue": true
}
]
}
Start by creating a type Input struct{} to describe the JSON that you're looking to parse, and a type Output struct{} for the JSON that you're looking to generate, and write a little code to convert from one to the other. You don't have to add all of the fields right away - you can start with just Event for example and add more until you've got them all.
I've done this in https://play.golang.org/p/PvpKnFMrJjN to show you, but I would recommend having only a quick read of it before trying to recreate it yourself.
A useful tool to convert JSON into Go structs is https://mholt.github.io/json-to-go/ but it will trip on RequestValue in your example which has several data types (and is therefore where we use interface{}).
I thing that you can use map like this:
package main
import (
"fmt"
)
type Event struct {
event string
values map[string]string
}
func main() {
eventVar := Event{event: "event", values: map[string]string{}}
eventVar.values["Id"] = "12345"
eventVar.values["vale1"] = "value"
fmt.Println(eventVar)
}
You just need to validate somehow that the id it's in there, this if you need values in the same level.
I hope this works for you.
I have the following structs declared in packageA
type FlagSkel struct {
Name string
Short string
HelpMsg string
}
type FlagString struct {
Value string
DefaultValue string
}
type CompositeFlagString struct {
FlagSkel
FlagString
}
In another package, I am trying to initialise (outside any function) a var of the later type as follows:
var Name = packageA.CompositeFlagString{
FlagSkel: {
Name: "name",
Short: "",
HelpMsg: "Something here",
},
FlagString: {
DefaultValue: "",
},
}
However vscode compiler shows me the attached error
What am I doing wrong?
You need to specify the type for the struct literals:
packageA.CompositeFlagString{
FlagSkel: packageA.FlagSkel{
Name: "name",
Short: "",
HelpMsg: "Something here",
},
FlagString: packageA.FlagString{
DefaultValue: "",
},
}
You missed to set the type of your inner structs you want to create.
your variable initialisation should be:
var Name = packageA.CompositeFlagString{
FlagSkel: packageA.FlagSkel {
Name: "name",
Short: "",
HelpMsg: "Something here",
},
FlagString: packageA.FlagString {
DefaultValue: "",
},
}
If you change this, it should work.
I'm using graphql union - union FolderOrFile = Folder | File. When I query for only folders I get array containing folder objects with empty objects that are basically the file objects.
TypeDefs
const typeDefs = gql`
union FolderOrFile = Folder | File
type Folder {
name: String
path: String
type: String
children: [FolderOrFile]
}
type File {
name: String
path: String
content: String
type: String
size: Int
ext: String
createdAt: String
}
type Query {
folders: Folder
}
`
Resolvers
const resolvers = {
FolderOrFile: {
__resolveType: obj => {
if (obj.type === "file") {
return 'File'
}
if (obj.type === "folder") {
return 'Folder'
}
},
},
Query: {
folders: async () => {
const data = await folders
.getFolder('./filesystem')
.then(response => response)
const appendData = await {
name: 'Folder',
path: './filesystem',
type: 'folder',
children: data,
}
return appendData
}
}
}
folders query
{
folders {
name
path
type
children {
... on Folder {
name
path
type
children {
... on Folder {
name
path
type
}
}
}
}
}
}
Response I get
{
"data": {
"folders": {
"name": "Folder",
"path": "./filesystem",
"type": "folder",
"children": [
{
"name": "Dishes",
"path": "./filesystem/Dishes",
"type": "folder",
"children": [
{},
{},
{
"name": "Non Vegetarian",
"path": "./filesystem/Dishes/Non Vegetarian",
"type": "folder"
},
{
"name": "Vegetarian",
"path": "./filesystem/Dishes/Vegetarian",
"type": "folder"
}
]
},
]
}
}
}
The response shouldn't have those empty objects which in this case is for files being returned as empty object. Similarly when I query for file I get folders as empty objects.
You have to specify inline fragments for all the possible types when querying a field that returns a union or interface. In your query, you are only using an inline fragment for the Folder type. You're telling the server "if the returned object is a Folder, I want these fields". But if the object resolves to any other type, like File, you end up with an empty selection set because you have not specified which fields you want for that particular type.
{
folders {
name
path
type
children {
... on Folder {
name
path
type
}
... on File {
# whatever your File fields are
}
}
}
}
I am unable to successfully return a populated instance of List<StringDictionary>> from Web API Controller to a C# console app. Here are the details...
Web API Code:
[HttpPost]
public async Task<HttpResponseMessage> Get(IEnumerable<long> ids)
{
var results = [assume populated instance of List<StringDictionary>>]
return Request.CreateResponse<List<StringDictionary>>(HttpStatusCode.OK, results);
}
I have the following client side code:
using (var httpClient = new HttpClient { BaseAddress = new Uri(baseAddress) })
{
var httpResponse = httpClient.PostAsJsonAsync<long[]>("api/promotions", mockIds).Result;
if (httpResponse.IsSuccessStatusCode)
{
var content = httpResponse.Content.ReadAsAsync<List<StringDictionary>>().Result; ***** DOES NOT WORK ****
}
}
I get the following error:
{"Cannot create and populate list type System.Collections.Specialized.StringDictionary. Path '[0]', line 1, position 2."}
What obvious fact am I missing here?
UPDATE - what's interesting is if I change StringDictionary to Dictionary it works great.
The difference is because of DeSerialization. JSON deserializer is not able to deserialize the format you are sending. If you just try to send single object you will get this error: Cannot create and populate list type System.Collections.Specialized.StringDictionary.
This link can help you getting more understanding.
Here is the JSON representation of serialized Dictionary and String dictionary.
Dictionary
[
{
"1": "A",
"4": "G"
},
{
"1": "A",
"3": "B"
}
]
String Dictionary
[
[
{
"_key": "4",
"_value": "G"
},
{
"_key": "1",
"_value": "A"
}
],
[
{
"_key": "3",
"_value": "B"
},
{
"_key": "1",
"_value": "A"
}
]
]