I have a JSON object say:
Json::Value temp;
temp["example1"] = "first";
which will be represented as
{
"example1" : "first"
}
Now if I want to add another object into the above object without using the index method, how can I do it? For example:
{
"example1" : "first",
"example2" : "second"
}
but avoiding using syntax
temp["example2"] = "second";
Are there any equivalents to push_back() (like in C++ vector/list) in JsonCpp?
The equivalent to push_back in JsonCpp is append, but you can use it only on Json::nullValue or Json::arrayValue.
That makes sense because only one parameter is needed to add an element to an array.
What are you asking is unclear/not possible, because you are trying to create an object, which is like a std::map in C++, and two parameters are needed to insert an element here.
Related
I'm a jq newbie, and I try to transform a json (a Swagger spec). I want to add an element to the array value of the "parameter" keys:
{
...
"paths": {
"/great/endpoint1": {
"get": {
"parameters": [] <<--- add a value here
}
}
"/great/endpoint2": {
"post": {
"parameters": [] <<-- and here too here too etc.
....
The following jqplay almost works. It adds values to the right arrays, but it has the nasty side effect of also removing the "x-id" value from the root of the input json. It's probably because of a faulty if-condition. As the paths contain a varying string (the endpoint names), I don't know how to write a wildcard path expression to address those, which is why I have tried using walk instead:
https://jqplay.org/s/az56quLZa3
Since the sample data is incomplete, it's difficult to say exactly what you're looking for but it looks like you should be using parameters in the call to walk:
walk(if type=="object" and has("parameters")
then .parameters += [{"extra": "value"}]
else . end)
If you want to restrict the walk to the top-level paths, you would preface the above with: .paths |=
I'm forming an xml whose snippet is -
<cache-properties>
<list-cache-hit-rate>
<units>hits/sec</units>
<value>1.5308452E6</value>
</list-cache-hit-rate>
<list-cache-miss-rate>
<units>misses/sec</units>
<value>25422.167</value>
</list-cache-miss-rate>
<compressed-tree-cache-hit-rate>
<units>hits/sec</units>
<value>970.2339</value>
Notice the value 1.5308452E6 is big enough that the values are stored as exponent while performing fn:sum() behind the scene.
Later, I'm converting the xml to json by the following function -
let $arr := json:to-array(local:tojson($data))
return (($data))
and value converted looks like this -
cache-properties": {
"list-cache-hit-rate": {
"units": "hits/sec",
"value": 1.5308452E6
},
"list-cache-miss-rate": {
"units": "misses/sec",
"value": "25422.167"
},
"compressed-tree-cache-hit-rate": {
"units": "hits/sec",
"value": "970.2339"
},
Notice the values are enclosed in quotes except 1.5308452E6 this value. This is not in quotes. What correction is needed here ? Or is this correct? I'd rather have all values in quotes. This is my custom transform function-
declare function local:tojson($func){
let $custom := let $config := json:config("custom")
let $_ := map:put( $config, "whitespace", "ignore" )
let $_ := map:put( $config, "array-element-names", "Video" )
return $config
return json:transform-to-json($func,$custom)
};
Take a look at the xml schema. Your snippets appear to be similar or identical to marklogic system status xml schema however you mention 'fn:sum in the background' so Im guessing you have applied a transformation which has changed the xsd type.
The json transformation code uses the XSD type if in scope to determine the typed output in JSON (for XML numeric types). Also if the number is 'too large' it can convert to string to avoid JavaScript issue.
( it basically uses fn:data(value) to convert )
If needed you can either force a string type onto your xml, or you can specialize the transformation by overriding one of the json-custom: primitives in json/custom.xqy by supplying the appropriate mapping in the config. Look into the source for the full list of overridable functions. They are not fully documented as they are not with full generality in mind and may not be obvious, easy or possibly to change behaviour in every conceivable way.
The strategies are to either
Use an XML with schema in scope that types atomic values explicitly (in your case as xs:string),
Override one of the low level functions in custom.xqy
Convert the JSON by post-processing and 'stringify' the desired elements
Roll your own (not too difficult with the samples show)
All of the above
I want to see if a variable exists - i.e. that I have created in.
if(exists(this.mydict))
{ //append my dict
}else
{
// initialize dict
}
Trouble is this fails on
Error in exists(this.mydict)
What am I doing wrong?
How can I extend the exists function to work with the following:
Any ideas how I would extend to this to looking at seeing whether a nested dictionary would also exist. I.e. for example: if(exists("mylists[[index]]['TSI']")), where the mylists object is a dictionary look up that also wants to contain a nested dictionary.
exists() function takes a character argument with the variable name:
if(exists("this.mydict")){
# you can use this.mydict here
}else{
# initialize this.mydict
# e.g. this.mydict <- "some value here"
}
Here is the definition of my Package class:
type Package ([<ParamArray>] info : Object[]) =
do
info |> Array.iter (Console.WriteLine)
member this.Count = info.Length
and here is the IL, I'm trying:
let ilGen = methodbuild.GetILGenerator()
ilGen.Emit(OpCodes.Ldstr, "This is 1")
ilGen.Emit(OpCodes.Ldstr, "Two")
ilGen.Emit(OpCodes.Ldstr, "Three")
ilGen.Emit(OpCodes.Newobj, typeof<Package>.GetConstructor([|typeof<Object[]>|]))
ilGen.Emit(OpCodes.Ret)
but this doesn't seem to work. I tried:
ilGen.Emit(OpCodes.Newobj, typeof<Package>.GetConstructor([|typeof<String>; typeof<String>; typeof<String>|]))
a well as:
ilGen.Emit(OpCodes.Newobj, typeof<Package>.GetConstructor([|typeof<Object>; typeof<Object>; typeof<Object>|]))
but it just laughs at me. What am I doing wrong?
The [<ParamArray>] attribute indicates to a compiler that a method accepts a variable number of arguments. However, the CLR doesn't really support varargs methods -- it's just syntactic sugar provided by the C#/VB.NET/F# compilers.
Now, if you take away the [<ParamArray>], what are you left with?
(info : Object[])
That is the signature of the constructor you're trying to call.
So, you'll need to use the newarr and stelem opcodes to create an array, store the values into it, then call the constructor using the array as the argument. This should do what you want (though I haven't tested it):
let ilGen = methodbuild.GetILGenerator()
// Create the array
ilGen.Emit(OpCodes.Ldc_I4_3)
ilGen.Emit(OpCodes.Newarr, typeof<obj>)
// Store the first array element
ilGen.Emit(OpCodes.Dup)
ilGen.Emit(OpCodes.Ldc_I4_0)
ilGen.Emit(OpCodes.Ldstr, "This is 1")
ilGen.Emit(OpCodes.Stelem_Ref)
// Store the second array element
ilGen.Emit(OpCodes.Dup)
ilGen.Emit(OpCodes.Ldc_I4_1)
ilGen.Emit(OpCodes.Ldstr, "Two")
ilGen.Emit(OpCodes.Stelem_Ref)
// Store the third array element
ilGen.Emit(OpCodes.Dup)
ilGen.Emit(OpCodes.Ldc_I4_2)
ilGen.Emit(OpCodes.Ldstr, "Three")
ilGen.Emit(OpCodes.Stelem_Ref)
// Call the constructor
ilGen.Emit(OpCodes.Newobj, typeof<Package>.GetConstructor([|typeof<Object[]>|]))
ilGen.Emit(OpCodes.Ret)
NOTE: In this code, I used the dup OpCode to avoid creating a local variable to hold the array reference while storing the element values. This is only feasible because this code is fairly straightforward -- I strongly suggest you create a local variable to hold the array reference if you want to build something more complicated.
I'm wrapping a C++ framework with boost::python and I need to make a C++ method overrideable in python. This is a hook method, which is needed by the framework and has a default implementation in C++, which iterates through a list (passed as parameter) and performs a choice. The problems arise because the choice is stated by returning a pointer to the chosen element (an iterator, in fact), but I can't find a way to return a C++ pointer as a result of a python function. Can anyone help?
Thanks
This is most certainly doable, but you don't really have enough details. What you really need to do is create a c++ function that calls your python function, proceses the python result and returns a c++ result. To paraphrase (let's assume I have a boost object called func that points to some python function that parses a string and returns an int):
using boost::python;
A* test(const std::string &foo) {
object module = import("mymodule");
object func = module.attr("myfunc");
// alternatively, you could set the function by passing it as an argument
// to a c++ function that you have wrapped
object result = func(foo);
int val = extract<int>(result);
return new A(val); // Assumes that you've wrapped A.
}
// file: https://github.com/layzerar/box2d-py/blob/master/python/world.cpp
struct b2ContactFilter_W: b2ContactFilter, wrapper<b2ContactFilter>
{
bool ShouldCollide(b2Fixture* fixtureA, b2Fixture* fixtureB)
{
override func = this->get_override("ShouldCollide");
if (func)
{
return func(ref(fixtureA), ref(fixtureB)); //ref is boost::ref
}
return b2ContactFilter::ShouldCollide(fixtureA, fixtureB);
}
bool ShouldCollideDefault(b2Fixture* fixtureA, b2Fixture* fixtureB)
{
return b2ContactFilter::ShouldCollide(fixtureA, fixtureB);
}
};
class_<b2ContactFilter_W, boost::noncopyable>("b2ContactFilter")
.def("ShouldCollide", &b2ContactFilter::ShouldCollide, &b2ContactFilter_W::ShouldCollideDefault)
;
Is this what you need ?