Output my JSON data before I use Firebase $save or $add in console? - json

I've been trying to debug for hours a Firebase rule problem and was wondering if there is something easier available.
My problem is that I save my firebaseObject with $save (or create with $add) and get a permission denied because of my rules. However, both the rules and the object is pretty complex and there are dozens of rules which are involved. In my simulator, I think I got it all, but still get permission denied.
The problem is that I am not 100% sure how the JSON data actually looks which $save tries to send to Firebase. If I use the normal console.log(myObject), I get of course a list of all values and functions inside this object, but this isn't the same as the raw JSON I would expect (like { "name": "value" }).
Is there any way to display the actual plain JSON data $save sends to copy this into the rule simulator and debug? Or is there any other way to see which exact permission is denied?
Otherwise, I have to go one by one, switching my permissions off and on which would be a pretty long night for me. :(

If the value of the $firebaseObject is an object, the only difference (in addition to the prototype-wired methods) should be a number of $-prefixed properties (like $id and $resolved). So you should be able to see the actual JSON of what will be written to the database using something like this:
var written = {};
Object.keys(myObject).forEach(function (key) {
if (key.charAt(0) !== "$") { written[key] = myObject[key]; }
});
console.log(JSON.stringify(written));
The $$hashKey entries mentioned in your comment are added by AngularJS. A more general mechanism could be used to remove/ignore all $-prefixed keys throughout the object:
console.log(JSON.stringify(myObject, function (key, val) {
return key.charAt(0) === "$" ? undefined : val;
}));

Related

Apps script JSON.parse() returns unexpected result, how can I solve this?

I am currently working on external app using Google Sheets and JSON for data transmission via Fetch API. I decided to mock the scenario (for debugging matters) then simple JSON comes from my external app through prepared Code.gs to be posted on Google sheets. The code snippet I run through Apps-scripts looks like this:
function _doPost(/* e */) {
// const body = e.postData.contents;
const bodyJSON = JSON.parse("{\"coords\" : \"123,456,789,112,113,114,115,116\"}" /* instead of : body */);
const db = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
db.getRange("A1:A10").setValue(bodyJSON.coords).setNumberFormat("#"); // get range, set value, set text format
}
The problem is the result I get: 123,456,789,112,113,000,000,000 As you see, starting from 114 and the later it outputs me 000,... instead. I thought, okay I am gonna explicitly specify format to be returned (saved) as a text format. If the output within the range selected on Google Sheets UI : Format -> Number -> it shows me Text.
However, interesting magic happens, let's say if I would update the body of the JSON to be parsed something like that when the sequence of numbers composed of 2 digits instead of 3 (notice: those are actual part of string, not true numbers, separated by comma!) : "{\"coords\" : \"123,456,789,112,113,114,115,116,17,18\"}" it would not only show response result as expected but also brings back id est fixes the "corrupted" values hidden under the 000,... as so : "{"coords" : "123,456,789,112,113,114,115,116,17,18 "}".
Even Logger.log() returns me initial JSON input as expected. I really have no clue what is going on. I would really appreciate one's correspondence to help solving this issue. Thank you.
You can try directly assigning a JSON formatted string in your bodyJSON variable instead of parsing a set of string using JSON.parse.
Part of your code should look like this:
const bodyJSON = {
"coords" : "123,456,789,112,113,114,115,116"
}
I found simple workaround after all: just added the preceding pair of zeros 0,0,123,... at the very beginning of coords. This prevents so called culprit I defined in my issue. If anyone interested, the external app I am building currently, it's called Hotspot widget : play around with DOM, append a marker which coordinates (coords) being pushed through Apps-script and saved to Google Sheets. I am providing a link with instructions on how to set up one's own copy of the app. It's a decent start-off for learning Vanilla JavaScript basics including simple database approach on the fly. Thank you and good luck!
Hotspot widget on Github

Setting value using UseState hook adds a "tableData" object to data fetched from API

I am fetching data from a flask API using Axios, then using the useState hook to use that data to build a table. The error I'm encountering is that after I use the setValue function to update the state, an extra "tableData:{id:0}" object is added to the JSON object the API returning, and it seems to happen after the setValue function is called.
I have already tried to use delete values.key.tableData when I was only dealing with single objects, but now that I have an array of objects it doesn't work anymore, and I don't understand why this key is even added in the first place.
I get an "undefined" error when I don't use the initial state like I did below.
The console shows the original string (not parsed yet) when i log the API's original response, but shows this when I log the state:
​
0: Object { Email: "", tableData: {…} }
​
length: 1
​
<prototype>: Array []
​
How do I keep the "tableData" key from being added to the response? Is there an issue with the way I'm using the hook?
The relevant parts of the code are down here:
React.useEffect(() => {
setLabelWidth(inputLabel.current.offsetWidth);
axios.get("http://127.0.0.1:5000/api",{params: { start: selectedstartDate, end: selectedendDate}}).then((response)=>{
console.log(response.data.details);
setValues(response.data.details);
console.log(values);
}, []);
After looking at the way MaterialTable behaves, the issue was created by it mutating whatever is passed as data, so in this case my state variable, and adding that extra key to render the table. To solve this, I added a second state variable which is a copy of the first one, that I only use for the table data prop, and kept using the original values for everything else.

How to identify duplicate keys when parsing a json object with json-cpp?

I am trying to parse a json object read from a file.
I want to identify duplicate keys, as json-cpp doesn't like them (even if they are not illegal in json).
I need to be able to say: ERROR: your json file has duplicate keys and we dont like that.
Json::Reader reader(Json::Features::strictMode());
Using reader in strictMode does not do the trick.
Set
rejectDupKeys
in
void Json::CharReaderBuilder::setDefaults ( Json::Value * settings )
JsonCPP Doc
There is no way out of the box, but you can program that functionality.
Since JsonCPP uses a map to store object keys, you have to add some code to:
Value &Value::resolveReference(const char *key, bool isStatic)
First, you have to be sure you are parsing (and not accessing some Json::Value). Then, you have to add something (like an exception or a flag) to this if:
if (it != value_.map_->end() && (*it).first == actualKey)
{
// key is already present: if parsing, throw!
return (*it).second;
}
Open an issue. That could be added easily. (Sga's idea might be the best way.) We've done a lot of work recently to make it easier to add features while maintaining binary-compatibility.

Does calling ko.mapping.fromJS two time is right thing to do?

I am using knockout mapping plugin to map JSON data to knockout view model. The issue is JSON comes from server data doesn't have all the properties always. But my computed obeservables refer them. So I creates all the observable in first mapping using an empty object(templateStructure) contains all properties and then doing seocond call with actual data to populate the observable with current data. This works fine but want to know that if there any better way to handle the situation?
This is how the two time call is happening right now. templateStructure is dummay object with all the properties and data is actual data.
ko.mapping.fromJS(templateStructure, {}, this);
ko.mapping.fromJS(data, {}, this);
Calling mapping.fromJS to update an existing view model is right. If you're receiving updates to your model using AJAX, it's the easiest way to do it (if you didn'd use mapping, you'd have to do it by hand, property by property).
Your approach of creating a "template viewmodel" with all the properties, so that they exist even if you don't receive it in you JSON responses is good. Besides, it's easier to understand the JavaScript code: you don't need to see the server side to discover which properties are in the view model, as would happen if you made the first mapping directly from the server.
However, if the received model is nearly complete, you can always customize the "create" of your mapping (You could look for missing observable properties using js hasOwnProperty and adding the missing ones). The last example of the docs in the link so precisely how to add a new observable (in this sample, a computed observable):
var myChildModel = function(data) {
ko.mapping.fromJS(data, {}, this); // this is the view model
this.nameLength = ko.computed(function() { // nameLength is added to the vm
return this.name().length;
}, this);
}
In this sample you could add the condition to create nameLength only if not present on the received data, like this:
if (!data.hasOwnProperty('nameLength')) {
/* add the missing observ. property here */
}
(NOTE: you can also customize the update, if needed).
I have solved it using jQuery extend method by merging the object before mapping. So I only needed one call to the mapping function.
var mergedData = jQuery.extend(true,data,templateStructure);
ko.mapping.fromJS(mergedData, {}, this);

Typescript with TypeLite - Run time type checking

Let's say I have some C# DTO's and I want to convert them to TypeScript interfaces using T4 templates and neat little library called TypeLite
On the client side, I have some concrete TypeScript classes (that inherit from Backbone.Model but that's not important) that represent the same DTO defined on the server side.
The intended goal of the interfaces is to act as data contracts and ensure client and server DTOs are kept in sync.
However, this is problematic since TypeScript supports no run-time type checking facilities other than instanceof. The problem with instance of is when I fetch my DTOs from the server they are plain JSON objects and not instances of my model. I need to perform run-time type checking on these DTOs that come in from the server as JSON objects.
I know I can do something like this:
collection.fetch({...}).done((baseModels) => {
baseModels.forEach((baseModel) => {
if(baseModel&& baseModel.SomeProperty && baseModel.SomeOtherProperty){
//JSON model has been "type-checked"
}
});
});
However, there is obvious problems to this because now I need to update in three places if I change or add a property.
Currently the only thing I found is this but it's undocumented, not maintained, and uses node which I have zero experience with so I'll save myself the frustration. Does anybody know of anything similar to perform run-time type checking in TypeScript or some other way to accomplish what I'm after?
It would be great if this was built into TypeLite to generate the interfaces as well as a JSON schema for type checking at run-time. Being that this project is open source somebody should really go ahead and extend it. I'd need some pointers at the least if I would do it myself (thus the question).
More details about my particular problem here (not necessary but if needed extra context)
At runtime you are using plain JavaScript, so you could use this answer as it relates to plain JavaScript:
How do I get the name of an object's type in JavaScript?
Here is a TypeScript get-class-name implementation that can supply the name of the enclosing TypeScript class (the link also has a static separate version of this example).
class ShoutMyName {
getName() {
var funcNameRegex = /function (.{1,})\(/;
var anyThis = <any> this;
var results = (funcNameRegex).exec(anyThis.constructor.toString());
return (results && results.length > 1) ? results[1] : "";
}
}
class Example extends ShoutMyName {
}
class AnotherClass extends ShoutMyName {
}
var x = new Example();
var y = new AnotherClass();
alert(x.getName());
alert(y.getName());
This doesn't give you data about the inheritance chain, just the class you are inspecting.