I want to make an if statement that checks if my JSON (item_section) has a null value at a certain key.
This code:
let my_dict = item_section[counter].dictionaryValue
print(my_dict["creator"])
prints: Optional(null) when the creator is not set.
If it is set if it prints the creator's name, like: user_729834892.
How can I make an if statement that checks if the creator is null?
Such as:
if ((my_dict["creator"]) == nil) { //This line does not work
my_dict["creator"] = "No Maker"
}
Try
if my_dict["creator"].type == .Null {
print("creator is null")
}
try this
print( my_dict.indexForKey( "creator") )
if (my_dict.indexForKey( "creator") == nil) {
my_dict["creator"] = "No Maker"
}
if the creator is not set then function indexForKey will return nil.
The JSON framework never returns an optional when indexing a dictionary (a JSON object). If the value doesn't exist, it rather returns the constant JSON.null, which you can compare:
if my_dict["creator"] == JSON.null {
my_dict["creator"] = "No Maker"
}
also method isExists would work
if !my_dict["creator"].isExists() {
my_dict["creator"] = "No Maker"
}
Related
I'm creating a rest api in golang and making a POST request into a table.
For this I've created a struct. Basically the vars in struct is same as the columns in table named users.
and written a function to make a POST request. And the code is working fine, the params while making POST request is being inserted successfully in the table.
type User struct {
ID int
Name string
Lname string
Country string
}
func insertUser(response http.ResponseWriter, request *http.Request)
{
var userDetails User
decoder := json.NewDecoder(request.Body)
err := decoder.Decode(&userDetails)
defer request.Body.Close()
if err != nil {
returnErrorResponse(response,request, httpError)
} else {
httpError.Code = http.StatusBadRequest
if userDetails.Name == "" {
httpError.Message = "first name can't be empty"
returnErrorResponse(response, request, httpError)
} else if userDetails.Lname == "" {
httpError.Message = "Last name can't be empty"
returnErrorResponse(response, request, httpError)
} else {
isInserted := insertUserInDB(userDetails)
if isInserted {
getAllUsers(response, request)
} else {
returnErrorResponse(response, request, httpError)
}
}
}
}
Here is insertUserInDB(userDetails) definition
func insertUserInDB(userDetails User) bool {
stmt, err := db.Prepare("insert into users set Name=?, Lname=?,
Country=?")
if err != nil {
fmt.Print("helper_methods.go : 118")
fmt.Println(err)
return false
}
_, queryError := stmt.Exec(tableName, userDetails.Name,
userDetails.Lname, userDetails.Country)
if queryError != nil {
fmt.Print("helper_methods.go : 125")
fmt.Println(queryError)
return false
}
return true
}
Is there any way to write a common function to insert record in any of the table in the DB?
Can we create struct dynamically, or any other way?
Please help me out here.
Like in other languages, you can use an ORM library to do the DB translation for you, for example GORM, or you can do the translation yourself. Since you already implemented saving the data manually, see this article for how to retrieve data manually.
If you just want to write a generic method that generates/executes SQL queries by matching struct field names you can use the reflect package of go. You will have to identify the structs fields by using reflect.TypeOf() to get the Type of your passed variable and then iterate over the StructField that you can get by using the Field() method on the Type. The StructField will reveal the Name and ValueOf() will allow you to access the Value. Name and value can then be used to construct the query.
For getting a better understanding I recommend you read some articles on reflect. Like this and this.
I think you can use package Refleciton in Golang
,at first step you have to create a method that generates a query for any given type
of struct, for example i write a method that generates an insert query for given
struct.
I have thus two type
type FirstType struct {
FirstParam string
SecondParam int
}
type SecondType struct {
FirstParam string
SecondParam string
ThirdParam int
}
My insert query generation method is as follow
func generateInsetMethod(input inrerface{}) (string, error) {
if reflect.ValueOf(q).Kind() == reflect.Struct {
query := fmt.Sprintf("insert into %s values(", reflect.TypeOf(q).Name())
v := reflect.ValueOf(q)
for i := 0; i < v.NumField(); i++ {
switch v.Field(i).Kind() {
case reflect.Int:
if i == 0 {
query = fmt.Sprintf("%s%d", query, v.Field(i).Int())
} else {
query = fmt.Sprintf("%s, %d", query, v.Field(i).Int())
}
case reflect.String:
if i == 0 {
query = fmt.Sprintf("%s\"%s\"", query, v.Field(i).String())
} else {
query = fmt.Sprintf("%s, \"%s\"", query, v.Field(i).String())
}
default:
fmt.Println("Unsupported type")
}
}
query = fmt.Sprintf("%s)", query)
return query, nil
}
return ``, QueryGenerationError{}
}
know you can use this function to generate your insert queries and also you can generate other functions for Update and etch query that you wants
My function to parse an array of properties to a json object looks like this:
var jsonObject = "[{"
for i in 1...table.count {
var str = ""
var insideStr = String()
for property in properties {
let filteredTable = table.value(forKey: property) as! [Any]
insideStr += "\"\(property)\": \"\(filteredTable[i - 2])\","
}
let index = insideStr.characters.index(insideStr.startIndex, offsetBy: (insideStr.count - 2))
insideStr = String(insideStr[...index])
str += "\(insideStr)}],"
jsonObject.append(str)
}
let index = jsonObject.characters.index(jsonObject.startIndex, offsetBy: (jsonObject.count - 2))
jsonObject = "\(String(jsonObject[...index]))"
return jsonObject
}catch let error { print("\(error)") }
My question is, is it possible to skip the first property because it always returns nil data?
You could delete the first property:
delete obj[Object.keys(obj)[0]];
otherwise slice like this:
Object.entries(obj).slice(1); //array of arrays [key,value], without the first.
Replace your for loop with a for...in style loop, and then add a where clause to exclude nils since you don't want to risk dealing with them.
for tableItem in table where tableItem != nil {
// Handle json here
}
Or, you can use higher order functions to remove all the nils, and then iterate through it like this:
table.filter({ $0 != nil }).forEach({ tableItem in // Do stuff with tableItem })
I have a rest api and am getting all data via Json then putting it in a IOS TableView. My issue is that some data is being returned as NULL in Json
"vote_status":null
I am trying to get that NULL value in swift and change it to a string "0" but am having a hard time doing so . I have this so far
if var vote_status = Stream["vote_status"] as? String {
if (vote_status == (vote_status)[NSNull]) {
vote_status = "0"
}
}
However I get this compile error:
Cannot subscript a value of type 'String' with an index of type
'(NSNull).Type' (aka 'NSNull.Type')
I am doing this because nil and null does not seem to work so I can't do this.
if (vote_status == nil) ...
You just need to conditionally cast your dictionary value to String and use the Nil Coalescing Operator ?? to assign "0" in case of failure null:
let vote_status = Stream["vote_status"] as? String ?? "0"
Swift 3.0
func checkNull(obj : AnyObject?) -> AnyObject? {
if obj is NSNull {
return nil
} else {
return value
}
}
object.feature = checkNull(dict["feature"])
try this
vote_status is NSNull
You can try this
func checkForNull(value:AnyObject) -> String
{
if(value as! NSObject == NSNull() || value as! String == "")
{
return " "
}
else
{
return value as! String
}
}
Try something like this:
if let category = Stream["vote_status"] as? String {
print(category)
} else {
print(category)
}
I am getting data from a URL and it is coming back in Json . What I am trying to do is color a certain button Blue if a particular Json column does not contain null or Nil . This is My Json
{"votes":"0","vote_status":null},{"votes":"1","vote_status":"11"}
as you can see the field vote_status returns as a String however if the value is null then it doesn't have any quotation marks around it . How can I check for Null values in my code
// This will store all the vote_status values
var VoteStatus = [String]()
// captures the value
if var vote_Status = Stream["vote_status"] as? String {
self.VoteStatus.append(vote_Status)
}
However I get an error fatal error: Index out of range
Which I am positive it is because the NuLL values does not have any strings . Is there a way I can check for NULL values and change them to something like "null" ? I have tried doing it this way
if var voteStatus = Stream["vote_status"] as? String {
if vote_Status == nil {
vote_Status = "null"
}
self.VoteStatus.append(vote_Status)
}
and it states that comparing non-optional value of type String to nil is always false . The code above compiles but gives an error on Runtime . I am new to Swift but any suggestions would be great..
The reason you're getting that compiletime error is that if this passes: if var voteStatus = Stream["vote_status"] as? String { then that is a guarantee that Stream["vote_status"] is a non-nil String value. If you want to do something different if that IS a nil, then just put an else statement:
if var voteStatus = Stream["vote_status"] as? String {
//Do whatever you want with a guaranteed, non-nil String
} else {
//It's nil
}
If you also want to treat the string "null" as a nil value, you can add one little bit:
if var voteStatus = Stream["vote_status"] as? String, voteStatus != "null" {
//Do whatever you want with a guaranteed, non-nil, non-"null" String
} else {
//It's nil or "null"
}
The index out of range error is likely caused by something that we're not seeing in your code. Is Stream itself an optional? In your second example are you forgetting to initialize your voteStatus array?
I'm trying to see if a .json file has multiple of the same keys
"gauge1":{
"name":"someName",
"name":"someName1"
}
is there a way in go to check if the key 'name' in the json is used more than once?
In go if you unmarshal the json file with multiple keys of the same name, it will rewrite the previously written key and gauge1.name will become someName1
Any help would be grateful thank you!
You can create a json.Unmarshaler string type that returns an error if it is assigned more than once while unmarshaling.
type singleAssignString string
func (s *singleAssignString) UnmarshalJSON(b []byte) error {
if s != nil && *s != "" {
return fmt.Errorf("multiple string assignment")
}
*s = singleAssignString(string(b))
return nil
}
https://play.golang.org/p/v4L1EjTESX
Handling this with the json.Decoder is probably to only way to properly get all the fields and return a good error message. You can do this with an embedded decoder inside the outer type's UnmarshalJSON method. A rough example might look like:
type Data struct {
Name string
}
func (d *Data) UnmarshalJSON(b []byte) error {
dec := json.NewDecoder(bytes.NewReader(b))
key := ""
value := ""
for dec.More() {
tok, err := dec.Token()
if err != nil {
return err
}
s, ok := tok.(string)
if !ok {
continue
}
switch {
case key == "":
key = s
continue
case value == "":
value = s
}
if key == "Name" {
if d.Name != "" {
return fmt.Errorf("multiple assignment to Name")
}
d.Name = s
}
key = ""
}
return nil
}
Supposedly you should use low-level decoding facilities of the encoding/json package—namely, it's Decoder type whose method Token() iterates over all the tokens in the input JSON stream.
Combined with a state machine and a map (or a hierarchy of maps) to keep parsed out values, this approach will allow you to check whether a sibling field with the same name already was seen in the JSON object being parsed.