Use nil instead of Optional(<null>) for null value in JSON - json

In Swift, NSJSONSerialization.JSONObjectWithData uses Optional(<null>) for null value in JSON. Is that possible to tell the parse to use nil instead (i.e., drop fields with null values because Swift Dictionary doesn't allow nil value)?

Optional() is an NSNull value. You can avoid error like this:
if !(myField is NSNull) {
//Whatever you want to do with myField when not null
} else {
//Whatever you want to do when myField is null
}

NSJSONSerialization uses NSNull objects, and that's what you're seeing; you can simply check for them by comparing to NSNull().

I would say this is a problem with your JSON schema. null and string are different types of things in JSON. The fact that your key can have a value that is sometimes null and sometimes a string seems to me that you guys are not following a rigorous schema.
A good design would have the key either not be there, or if it is there, its value is guaranteed to be a string. Accessing the dictionary key in Swift produces an optional, which is nil if the key is not there, or a value if the key is there (in which case you know it's a string), which matches what you want.

Related

Handle JSON With null Inside Array With Kotlin

I am trying to handle null or empty JSON value fields value which has received both JSON case:
{
"field": [
null
]
}
and
{
"field": []
}
The case when an empty array works fine for me: If I get an object with an array size of 0, it means it is empty. In the second case, when the field's value is [null], I get an array size 1 with all the elements null. That is why I check the null case with the following approach:
val deserializedJson = jacksonObjectMapper().readValue<DataSimpleClass>(theJsonAsText)
if (deserializedJson.field.size == 1 && deserializedJson.field[0] == null) {
throw Exception()
}
Is there any better or more elegant approach to check such a [null] case?
I deserialize the JSON using jacksonObjectMapper() object version 2.9.8. Also, I have created a two-data class that looks like that:
#JsonInclude(JsonInclude.Include.NON_NULL)
data class DataSimpleClass(
#JsonInclude(JsonInclude.Include.NON_NULL)
val field: List<SpecificClass>
)
#JsonInclude(JsonInclude.Include.NON_NULL)
data class SpecificClass(
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonProperty("field1") val field1: String,
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonProperty("field2") val field2: String,
#JsonProperty("field3") val field3: String? = null,
val updateTime: Instant = Instant.now(Clock.systemUTC())
)
Also, I don't understand how Kotlin (null-safe language) may let me create a field when all the elements are null. How is it possible that Kotlin doesn't catch null while I send the non-nullable field null value The deserializedJson result, then the JSON key's value is null ?
I was expecting that the null won't be deserialized cause of its null value, as the object DataSimpleClass holds a non-nullable field.
In addition, my IntelliJ shows me that due to the null safe fields, the following condition "is always false" while, in fact, it is actually true during the run.
How is it possible that the value shouldn't be null due to the null safe, but it all gets null during the run time?the IntelliJ warning for wrong condition result
Kotlin is "null-safe" language because it enforces non-null-ability by default.
You can still have nulls in Kotlin - e.g. val foo: String? = null
The IDE just says that based on your definition it shouldn't be null and it will not allow you(at compile time) to put null there. Runtime is where don't have control over who/what puts null there.
If there is no guarantee that you will not receive null there you should sanitize it before assuming there are no nulls.
deserializedJson.field..filterNotNull()
If you would rather that it crashed the whole app I think you can set
.addModule(KotlinModule(strictNullChecks = true))
when configuring Jackson.

How to process null value inside json string using lua?

I am using lua in asterisk pbx. I encounter following problem while processing json string.
json "null" value converted to function type in lua. why?
how to handle this scenario? because i am expecting nil because no value means null in json and nil means nothing in lua.
local json = require( "json" )
local inspect = require("inspect")
local myjson_str='{"Sms":{"key":"xxxxxxxxxxxxxxxxxxxxx","to":"{caller}","senderid":null,"type":"Simple","content":"Your request has been accepted in Previous Miss call. We get back to you very soon."}}'
local myjson_table = json.decode(myjson_str)
print(type(myjson_table["Sms"]["senderid"]))
print(myjson_table)
print(inspect(myjson_table))
print(json.encode(myjson_table))
out put for above is
function
table: 0xf5e770
{
Sms = {
content = "Your request has been accepted in Previous Miss call. We get back to you very soon.",
key = "xxxxxxxxxxxxxxxxxxxxx",
senderid = <function 1>,
to = "{caller}",
type = "Simple"
}
}
{"Sms":{"type":"Simple","key":"xxxxxxxxxxxxxxxxxxxxx","senderid":null,"content":"Your request has been accepted in Previous Miss call. We get back to you very soon.","to":"{caller}"}}
It is up to specific library to decide how to represent null value.
Using nil has its own problem because its not possible find either
original JSON has key with null value or there no such key at all.
So some libraries just return some unique value. Some provide
a way to pass this value like json.deconde(str, NULL_VALUE).
So answer is just read the doc/source of library you use.
Most likely it provide something like json.null value to check
either value is null. But function is really strange choice because
they have some undetermined rules of uniqueness.
Or try another library.
First of all, #moteus is right:
It is up to specific library to decide how to represent null value
If you're using the JSON library by Jeffrey Friedl the solution is to use a placeholder instead of null and serializing the table structure to a json string using designated encode options:
-- define a placeholder
NullPlaceholder = "\0"
-- use it in an internal table
tableStructure = {}
tableStructure['someNullValue'] = NullPlaceholder
-- pass the placeholder to the encode methode
encode_options = { null = NullPlaceholder }
jsonString = JSON:encode(tableStructure, nil, encode_options)
which leads to
{"someNullValue": null}

Unmarshal inconsistent JSON

I have JSON (that I cannot control) like this:
{
"foo1":{
"a":{
"up":10,
"down":5
}
},
"foo2":{
"a":{
"up":1,
"down":1
}
},
"bar":{
"up":11,
"down":6
}
}
"foo1" and "foo2" are dynamic.
How can I properly unmarshal this structure in go?
It would be okay if I could just tell go to not try to deserialize "bar" (the inconsistent property).
Go will by default ignore fields unspecified in the struct you unmarshal into.
In this case, your structure would be set up like this:
type NestedProp2 struct {
Up int
Down int
}
type NestedProp struct {
A NestedProp2
}
type Prop struct {
Foo1 NestedProp
Foo2 NestedProp
}
When you call the the json.Unmarshal function, the extra property will not be deserialized:
var prop Prop
err := json.Unmarshal(jsonBlob, &prop)
if err != nil {
fmt.Println("error:", err)
}
fmt.Printf("%+v", prop)
So you get the following output:
{Foo1:{A:{Up:10 Down:5}} Foo2:{A:{Up:1 Down:1}}}
You can see it in action here.
You said:
I have JSON (that I cannot control)
So to what extent you could control? Here I could provide you with some scenario, and hope some of them match your purpose :)
Remember the general rule first:
In Golang, if a JSON key failed to find a matched field in struct, it will not be unmarshalled.
This means, for a key name in a JSON struct, when unmarshalling, it will look for a field in a golang struct at the same level with the same name case-insensitively. If this search failed, this key won't be unmarshalled.
For example, a key named foo1 will look for a field name foo1 in a golang struct at the same indent level. However it also matches with Foo1 or FoO1, since this matching is case-insensitive.
Remember, you could use field tag to specify the field name as well. Please take a look at the official page.
The value of some of the JSON fields are not consistent, and they could be ignored.
This is the case #gnalck solved in his answer. According to the general rule, if those inconsistent field failed to find a match, they will not be unmarshalled. Therefore, just don't put those inconsistent fields in the struct and you will be fine.
The value of some of the JSON fields are not consistent, but they could not be ignored.
In this case, #gnalck failed since those fields could not be ignored. Now a better way is to unmarshal bar into a json.RawMessage, so that you could unmarshal later.
The keys of the JSON object is undetermined, and their value is undetermined as well.
In this case, we could unmarshal the whole JSON object into a map[string]json.RawMessage, and unmarshal each fields later. When unmarshalling to a map, you could iterate through the map to get all the fields, and unmarshal them into a proper struct later.

How to stop null value fields from being marshalled in Grails

I am using Grails 1.3.7 and have the following DTO
class Result {
String key
List errors
}
Now either the key or the errors will be present, but not both. If the Result has a key, I don't want the marshalled JSON to have the errors field with a null value as shown below
{"errors":null,"key":"abcde"}
I looked at configuration options for the converter and it does not have an option for suppressing null values. I also looked at the last section on that page titled 'Customizing Converters Results' and registered an object marshaller as follows
class Result {
static {
grails.converters.JSON.registerObjectMarshaller(Result) {
return it.properties.findAll {k,v -> v != null}
}
}
}
But still the result contains errors with the null value. I am looking for the cleanest way to achieve this for both XML and JSON.
Trying this Grails 2.0.3 results in an error indicating conflict between the errors field and GORM's automatically-added grails.validation.ValidationErrors field (also named errors). Your marshaller looks OK, so you may just need to change your field name to something other then errors?

A JSON text must at least contain two octets

I received this error, and I couldn't find any reasonable answer to this question, so I thought I'd write a summary of the problem.
If you run this snippet in irb:
JSON.parse( nil )
You'll see the following error:
TypeError: can't convert nil into String
I was kind of expecting the function to return nil, and not a TypeError. If you convert all input using to_s, then you'll see the octet error:
JSON::ParserError: A JSON text must at least contain two octets!
That's just fine and well. If you don't know what an octet is, read this post for a summary and solution:
What is a JSON octet and why are two required?
Solution
The variable you're passing in is an empty string. Don't attempt to use an empty string in the JSON.parse method.
Question
So, now I know the cause of the error, what pattern should I use to handle this? I'm a bit loathe to monkey patch the JSON library to allow nil values. Any suggestions would be greatly appreciated.
parsed = json && json.length >= 2 ? JSON.parse(json) : nil
But really the library should be able to handle this case and return nil. Web browsers with built-in JSON support seem to work just like you expect after all.
Or to do it with a only slightly intrusive mini patch:
module JSON
def self.parse_nil(json)
JSON.parse(json) if json && json.length >= 2
end
end
parsed = JSON.parse_nil(json)
data.presence && JSON.parse(data)
JSON.parse(data.presence || '{}')
According to json.org
JSON is built on two structures:
A collection of name/value pairs. In various languages, this is realized as an object, record, struct, dictionary, hash table, keyed list, or associative array.
An ordered list of values. In most languages, this is realized as an array, vector, list, or sequence.
So, minimum two octets(8 bits) required at the top level would be {} or []
IMO, the best solution would be to make sure the argument to JSON.parse is either an strigified object or a strigified array. :-)
hash = JSON.parse(json) rescue {}
array = JSON.parse(json) rescue []
string = JSON.parse(json) rescue ''