Replicating JSON.Stringify - json

I have a practice problem and I need to replicate JSON.stringify, without actually using JSON.stringify. I was having trouble getting to the return value when it's an object that your inputting into the function. For example, if you insert
var obj = {a:1, b:2, c:3};
JSON.stringify (obj); // returns "{"a":1,"b":2,"c":3}"
That being said, I was trying to use a for in loop to set the property to the string value of the object that's being passed through. I was doing this only for an object container, but the function should actually work with anything you pass through it and it would JSON.stringify it.
var stringifyJSON = function(obj) {
var newObj = {};
for (var prop in obj){
newObj ={
stringProp:obj[prop]
};
}
return newObj;
};
I think I have the array portion down. I'm pretty terrible with object traversing. The result here is 'Object {stringProp:3}'. This is a practice problem within a recursion problem set, so I think they don't want me to use a loop. I was just trying to make it a little simpler by looping it, and then I would try to replicate it through recursion.
Any help would be appreciated!
Thanks,
B

Since it is a practice problem I'll just try to point you in the right direction:
You will need a loop in the code, as you will be required to recursively loop over each property in the object.
As for the recursive part, first you need to define your 'base case'. What is the condition based on the input that should not result in a recursive call? I'll give you a big hint, it's when the argument is not an object.
The tricky part for you is determining how you are going to be appending the resulting string from the recursive calls.
Some basic template code to start you off:
function myStringify( obj ) {
if ( typeof obj !== 'object' ) {
// base case
return ""+obj;
}
var str = "";
for ( var prop in obj ) {
if ( obj.hasOwnProperty( prop ) ) {
// recursive calls and string formatting magic
}
}
return str;
}

Related

Why is one way of json to object working and the other throwing null error? Dart/Flutter null safety trouble

I'm learning how to use json, not used to Dart null safety & I don't like it so far. But I will have no choice but to adapt to it. I'm trying to parse my json object list into a list of objects. I was able to work out the basics in my main, but when I attempt to create an actual method in a class using the same structure I'm getting a null error. As far as I can tell I'm doing the exact same thing in both with addition of the loop for iterating the entire json list.
Note: I of course did try inserting the optional ? where it asks but the IDE will not allow this.
Can someone help with explaining what I'm doing wrong here?
Error for class method jsonToDatabaseSyncItem()
lib/services/remote_database_services.dart:52:43: Error: Property 'length' cannot be accessed on 'List<dynamic>?' because it is potentially null.
- 'List' is from 'dart:core'.
Try accessing using ?. instead.
final jsonListLength = jsonObjectList.length;
^^^^^^
lib/services/remote_database_services.dart:55:38: Error: Operator '[]' cannot be called on 'List<dynamic>?' because it is potentially null.
- 'List' is from 'dart:core'.
var jsonObject = jsonObjectList[index]['DatabaseSyncItem'];
Class method (class- RemoteDatabaseService)
// This method will get server database
Future<List<dynamic>?> getRemoteDatabase() async {
final events = QueryBuilder<ParseObject>(ParseObject('Event'));
final apiResponse = await events.query();
if (apiResponse.success && apiResponse.result != null) {
return apiResponse.results;
} else {
return [];
}
}
// Method to parse json result list back to objects
Future<List<dynamic>?> jsonToDatabaseSyncItem() async {
final remoteDatabaseList = await getRemoteDatabase();
final jsonObjectList = await Future.value(remoteDatabaseList); /// This method throws the above
final jsonListLength = jsonObjectList.length; /// error when run in main
for (var index = 0; index == jsonListLength; index++) {
var jsonObject = jsonObjectList[index]['DatabaseSyncItem'];
print(jsonObject);
}
}
Main file working code
Future<void> main(List<String> arguments) async {
final test = remoteDatabaseServices.getRemoteDatabase();
Future<List<dynamic>?> getList() {
return Future.value(test);
}
var list = await getList();
print(list?.length);
var jsonObject = list![0]['DatabaseSyncItem'];
print(jsonObject);
var toObject = DatabaseSyncItem.fromJson(jsonObject);
print(toObject);
}
Your problem with null-safety seems to be a missing understanding about the feature. I will recommend you to read through the documentation here and read all the chapters: https://dart.dev/null-safety
About your code, you should consider when something can be null and when you can check the null and handle that case. In your example, it seems like getRemoteDatabase() should just return an empty List if an error happens or no result is returned. So we don't need to have the return type of this method as Future<List<dynamic>?> if we rewrite the method a bit:
Future<List<dynamic>> getRemoteDatabase() async {
final events = QueryBuilder<ParseObject>(ParseObject('Event'));
final apiResponse = await events.query();
if (apiResponse.success) {
return apiResponse.results ?? <dynamic>[];
} else {
return <dynamic>[];
}
}
(the ?? operator will here test if apiResponse.results is null, if that is the case, we return <dynamic>[]. If not, we use the value of apiResponse.results).
Since this method is now guarantee to never return null, we can use that to simplify the next method. I have also rewritten it to use a for-each loop since we don't really need the index of each element.
Future<void> jsonToDatabaseSyncItem() async {
final jsonObjectList = await getRemoteDatabase();
for (final jsonObject in jsonObjectList) {
print(jsonObject['DatabaseSyncItem']);
}
}
I have also removed this line since it does nothing at all. If remoteDatabaseList is a Future you should just await on that instead of creating a new Future.
final jsonObjectList = await Future.value(remoteDatabaseList);
Also, the return type of jsonToDatabaseSyncItem() have been changed to Future<void> since we are never returning any value.
I am a little confused about your main but I think this is where it is most clear that you got a confused about Future and null-safety. I have tried to rewrite it so it is much cleaner but should still do the same:
Future<void> main(List<String> arguments) async {
final list = await getRemoteDatabase();
print(list.length);
final dynamic jsonObject = list[0]['DatabaseSyncItem'];
print(jsonObject);
final toObject = DatabaseSyncItem.fromJson(jsonObject);
print(toObject);
}

How to manage visibility in multiple Observable calls?

I developped an Angular2 service to retrieve a list a categories from a backend server and count how many 'links' exist per category.
Once I have the number of links for each category, I add a property to the Json object to 'store' the value.
Here is the code:
nbLinks = '';
...
getCategories() {
return this.category.find({where: {clientId: this.userApi.getCurrentId()}}).map((data) => {
this.categoriesList = data;
for (var i = 0; i < this.categoriesList.length; i++) {
var obj = this.categoriesList[i].id;
this.category.countLinks(obj).subscribe((linksCount) => {
this.nbLinks = linksCount;
}, err => {
console.log(err);
});
}
return data;
},
err => {
console.log(err);
}
);
I am getting the categories in a json object with the correct 'where' clause.
I am looping on the Json to 'count' the number of link in this category.
My problem is that outside the for loop (getting out) the variable i is bigger than my Json length so the app is crashing.
My second problem is that I do not have the visiblity of this.nbLinks outside the for ... loop.
Thanks an Regards
I'm not sure I understand your code, but two things stand out:
1) It looks like you're mixing synchronous and asynchronous code. It cannot work.
Sync code: the for loop. Async code: the observable.
Instead, could you refactor your code to ONLY work with observables and chain all the operations? You can wrap any piece of data in an observable with Observable.from() or Observable.of().
For instance:
getCategories() {
const categories = this.category.find({where: {clientId: this.userApi.getCurrentId()}});
return Observable.from(categories)
.map(category => countLinksInCategory(category));
}
If countLinksInCategory() is an async operation, then have that function return an Observable, and use .mergeMap() instead of .map() in the code above.
2) Try avoiding setting an outside variable from within your observable
// This part is not ideal
Obs.subscribe(linksCount => {
this.nbLinks = linksCount;
});
I would suggest renaming getCategories() to getNumLinks() to reflect the role of the function. The only job of the Observable inside this function is to produce a value. Then, the consumer of the Observable can use that value (i.e. assign it, display it...).
In terms of code:
getNumLinks(): Observable<number> {
// Here, count the number of links - See example code above.
// Eventually, return an observable wrapping the final value.
}
Then, elsewhere in your code:
// This is where you assign the value returned by the Observable.
// Note that we are OUTSIDE the Observable now.
getNumLinks().subscribe(numLinks => this.nbLinks = numLinks);

Is it possible to declare and call a dictionary of functions in TypeScript?

I'm doing a bit of refactoring and was wondering whether it's possible to declare and initialise a dictionary of factory functions, keyed on an enumerator, such that it can be used as a lookup for factory functions which can then be called? Or, alternatively, whether I'm going the wrong way about this and am missing a more elegant solution. I followed this answer to declare and initialise a typed dictionary but I'm unsure as to whether I've declared the signature correct or not, such that the key is a number and the value is a function. I've simplified my code into a very generic example - I'm aware it's rather contrived but the intent is much clearer this way.
// Types are enumerated as I have several different lists of types which I'd like to
// implement as an array of enumerators
enum ElementType {
TypeA,
TypeB,
TypeC
}
// Here, I'm trying to declare a dictionary where the key is a number and the value is a
// function
var ElementFactory: { [elementType: number]: () => {}; };
// Then I'm trying to declare these factory functions to return new objects
ElementFactory[ElementType.TypeA] = () => new ElementOfTypeA();
ElementFactory[ElementType.TypeB] = () => new ElementOfTypeB();
ElementFactory[ElementType.TypeC] = () => new ElementOfTypeC();
// And finally I'd like to be able to call this function like so such that they return
// instantiated objects as declared in the code block above
var a = ElementFactory[ElementType.TypeA]();
var b = ElementFactory[ElementType.TypeB]();
var c = ElementFactory[ElementType.TypeC]();
Your code is mostly correct and this approach will work, but there's one thing that can be improved:
// Here, I'm trying to declare a dictionary where the key is a number and the value is a
// function
var ElementFactory: { [elementType: number]: () => {}; };
In a type definition, () => {} means "a function that takes zero parameters and returns a {}". You can modify the return type here to be more specific, but unfortunately you will still need to manually express the type of the returned values whenever you call these factory functions. For example, you can do this:
type AnyElementType = ElementOfTypeA | ElementOfTypeB | ElementOfTypeC;
var ElementFactory: { [elementType: number]: () => AnyElementType; };
...
// this type declaration will not work
var a: ElementOfTypeA = ElementFactory[ElementType.TypeA]();
// but these will
var b = <ElementOfTypeB>ElementFactory[ElementType.TypeB]();
var c = ElementFactory[ElementType.TypeC]() as ElementOfTypeC;

What's the Reactive way to collapse elements into an array?

Take the following TypeScript/Angular 2 code sample:
query(): Rx.Observable<any> {
return Observable.create((o) => {
var refinedPosts = new Array<RefinedPost>();
var observable = this.server.get('http://localhost/rawData.json').toRx().concatMap(
result =>
result.json().posts
)
.map((post: any) => {
// Assume I want to convert the raw JSON data into a nice class object with
// methods, etc.
var refinedPost = new RefinedPost();
refinedPost.Message = post.Message.toLowerCase();
refinedPosts.push(refinedPost);
})
.subscribeOnCompleted(() => {
o.onNext(refinedPosts);
})
});
}
Written out, the database is returning JSON. I want to iterate over the raw JSON and create a custom object, eventually returning to subscribers an Array<RefinedPost>.
The code works and the final subscribers get what they need, but I can't help but feel like I didn't do it the "Reactive Way". I cheated and used an external accumulator to gather up the elements in the Array, which seems to defeat the purpose of using streams.
So, the question is, is there a better, more concise, reactive way to write this code?
Answering my own question.
query(): Rx.Observable<any> {
return this.server.get('http://localhost/rawData.json').toRx().concatMap(
result =>
result.json().posts
)
.map((post: any) => {
var refinedPost = new RefinedPost();
refinedPost.Message = post.Message.toLowerCase();
return refinedPost;
}).toArray();
}
This removes the internal accumulator and the wrapped Observable. toArray() took the sequence of items and brought them together into an array.

Difference: Riak.mapValuesJson() and JSON.parse()

I am wondering if there is any difference between Riak.mapValuesJson() and JSON.parse(). I did not know about Riak.mapValuesJson() so in my map reduce functions in my Riak database i kept using JSON.parse() which worked I am not sure if there are extra optimizations or something that are in the built in riak version of if Riak.mapValuesJson() is an alias of JSON.parse()
It uses JSON.parse()
See: https://github.com/basho/riak_kv/blob/master/priv/mapred_builtins.js
mapValues: function(value, keyData, arg) {
if (value["not_found"]) {
return [value];
}
var data = value["values"][0]["data"];
if (Riak.getClassName(data) !== "Array") {
return [data];
}
else {
return data;
}},
mapValuesJson: function(value, keyData, arg) {
if (value["not_found"]) {
return [value];
}
var newValues = Riak.mapValues(value, keyData, arg);
return newValues.map(function(nv) { return JSON.parse(nv); });
}
Edit:
The first step is in the if statment to make sure there is a value to the object because riak will return an object even if there is no value, allowing you to set a value.
The next step is calling the parent object and calling that method using a call back to parse the now decoded json data, there should not be any major speed differance between the two it adds to if stements and initalizing an object, but it does make the calling of the map reduce easier, I would use this on smaller buckets and the JSON.pare() on larger buckets