What is the best way to update JSON without duplicates, especially in the context of using CasperJS?

I am currently utilizing CasperJS to extract inner texts from webpages and store them in a JSON file.

Below you can find the code I am using along with an issue that I am encountering!

var words = [];
var casper = require('casper').create();
var x = require('casper').selectXPath;
var fs = require('fs');

function getWords() {
    var words = document.querySelectorAll('span.inner_tit');
    return Array.prototype.map.call(words, function(e) {
        return e.innerHTML;
    });
}

function createFinal(wordArray) {
    var out = [];
    wordArray.forEach(function(word) {
        out.push({"type": "river", "name": word, "spell": word.length});
    });
    return out;
}    

casper.start('http://dic.daum.net/index.do?dic=kor');


casper.thenClick(x('//*[@id="searchSubmit"]'), function(){
    console.log('searching');
});

casper.wait(2000, function() {
    casper.then(function() {
        words = this.evaluate(getWords);
    });
});

casper.wait(3000, function() {
    casper.thenClick(x('//*[@id="mArticle"]/div[2]/a[2]'), function (){
        words = words.concat(this.evaluate(getWords));
    });
});

casper.run(function() {
    var my_object = { "my_initial_words": createFinal(words)};
    this.echo(JSON.stringify(my_object, null, '\t'))
    var result = JSON.stringify(my_object, null, '\t')
    fs.write('myresults.json', result, 'a');
    this.exit();

});

The issue with this code is when the JSON code looks like this:

{
    "my_initial_words": [
        {
            "type": "river",
            "name": "apple",
            "spell": "5"
        },
        {
            "type": "river",
            "name": "banana",
            "spell": "6"
        }   
    ]
}

The program appends everything including the name of the JSON arrays like this:

{
    "my_initial_words": [
        {
            "type": "river",
            "name": "apple",
            "spell": "5"
        },
        {
            "type": "river",
            "name": "banana",
            "spell": "6"
        }   
    ]
}  {
    "my_initial_words": [
        {
            "type": "river",
            "name": "apple",
            "spell": "5"
        },
        {
            "type": "river",
            "name": "banana",
            "spell": "6"
        }   
    ]
}

To solve this issue, only these elements should be added (without "my _initial_words: []"):

{"type": "river",   "name": "apple","spell": "5"},
{"type": "river",   "name": "banana","spell": "6"}  

Answer №1

Updating an object in JSON file

In dealing with JSON, it's important to note that appending an object to an existing one may not result in valid JSON. However, there are steps you can take to update an object in a file:

  1. Retrieve the previous serialized JSON string.
  2. Parse the string into an object.
  3. Add new values to the object.
  4. Serialize the updated object.
  5. Override the existing file with the new data.

Here is an example of how this can be done:

var previousDataString = fs.read('myresults.json');
var previousData = JSON.parse(previousDataString);
previousData["my_initial_words"] = previousData["my_initial_words"].concat(createFinal(words));
var newData = JSON.stringify(previousData, null, '\t')
fs.write('myresults.json', newData, 'w');

Writing chunks of JSON to a file

If you prefer to write your data file in separate JSON chunks, you can follow this approach:

// Combine all items into a single string
var newItemsString = createFinal(words).reduce(function(combinedString, currentItem){
    return combinedString + JSON.stringify(currentItem) + "\n";
}, "")
// Append new items to previous content
fs.write('myresults.json', newItemsString, 'a');

Each item (word's object) will be written on its own line, allowing for easy retrieval when reading the file in another process.

Tackling premature exits

One thing to consider is how CasperJS handles exiting. If using a callback with casper.run(), remember to explicitly call casper.exit() at the right moment to exit the process. Avoid prematurely calling exit():

this.echo(JSON.stringify(previousData, null, '\t')).exit();
//                                                 ^^^^^^^ calling exit
var newData = JSON.stringify(previousData, null, '\t'); // not executed
fs.write('myscript.json', newData, 'w');  // not executed

Ensure the exit function is placed correctly within the callback or outside of casper.run():

this.echo(JSON.stringify(previousData, null, '\t'));
var newData = JSON.stringify(previousData, null, '\t');
fs.write('myscript.json', newData, 'w');
this.exit();  

Alternatively, move your final code outside of casper.then() and into casper.run():

casper.then(function() {
    var previousDataString = fs.read('myscript.json');
    var previousData = JSON.parse(previousDataString);
    previousData["my_initial_words"] = previousData["my_initial_words"].concat(createFinal(words));
    this.echo(JSON.stringify(previousData, null, '\t'));
    var newData = JSON.stringify(previousData, null, '\t')
    fs.write('myscript.json', newData, 'w');
});
casper.run();

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

IntellJ Editor encounters Typescript error

Currently engaged in a project using Angular 1.6 and Typescript. Up until recently, there were no compilation errors to be found. However, I am now encountering some peculiar errors. The code remains unchanged and the application is functioning properly. ...

Tips for effectively crafting a component capable of managing both a value and an observable for that specific value

I'm actually curious about two things. When is it appropriate to pass an observable of an object into a component versus resolving it with the | async method? If I want to create a versatile reusable component that can handle both scenarios - accept ...

Does the String.replace() function in Javascript have the capability of incorporating line breaks?

Is it possible to use the String.replace() method in JavaScript to replace any character with a line feed symbol? For example: newString = oldString.replace(/x/, "linefeed character (\n)"). ...

"Encountered an error with resolving the dependency tree during the installation of npm react-facebook-login, known as ERESOLVE

Having trouble installing npm react-facebook-login in my react application due to dependency errors. It's a bit daunting, and I'm hesitant to forcefully install something that could lead to issues down the line. Since I am new to JavaScript, what ...

Is there a way to streamline routing in AngularJS similar to how .NET Data Annotation automates tasks?

Understanding the routing system in AngularJS is key, as shown below: .when('/96', { templateUrl: "96.html", animation: 'present' }) .when('/96/moharram', { template ...

Is it possible to bind to a service variable in a controller without using $scope and utilizing the

As I delve into the world of controllerAs syntax in AngularJS, I've encountered a snag when attempting to bind a service variable. The traditional approach using `$scope.$watch` or `$scope.$on` would require injecting `$scope`, which seems counterintu ...

Utilize onClick and state in ReactJS to dynamically show a selected group of elements

I have recently delved into the world of React and I've encountered a puzzling question My query revolves around manipulating a list of items based on their type. Essentially, I wish to exhibit a subset of the list upon clicking a button. It's a ...

Is there a way for me to convert my (TypeScript Definition) .d.ts file into a (JavaScript) .js file?

It seems that there are plenty of guides available on converting a file from .js to .d.ts, but not the other way around. Specifically, I have some code in .d.ts format and I would like to convert it into JavaScript. Can anyone offer assistance with this t ...

A helpful guide on Sending parameters to a route using an object

I am attempting to transfer data with passing parameters from page1 to page2. Below is the code snippet from page1 : axios({ method: 'post', url: "http://127.0.0.1:8000/api/masuk", data: { ...

Is Implementing Toast Notifications in a MobX Store Considered a Poor Practice?

When a file is uploaded using an input field, the size of the file is extracted and checked when the onChange event occurs. If the file size exceeds the limit that can be accepted, an error message in form of a toast notification would be displayed. Is th ...

Connect images from local files to an array in the API through Vue.js and axios

Hey there, I'm a newbie when it comes to Vue and the axios library, so I could really use some major assistance. Currently, I have an API that's sending me back an array of data. Here's a snippet from the API: "potions": { &qu ...

When an array is prototyped as a member of a JavaScript object, it becomes a shared property among all instances

Is anyone else surprised by this behavior? It really caught me off guard... I was expecting prototyped arrays to be private to each instance of a class rather than shared across all instances. Can someone confirm if this is the intended behavior and provi ...

Downloading a file through a JavaScript link in HTMLUnit: A step-by-step guide

Looking to download a file with HTMLUnit from a javascript link is proving to be quite challenging. The journey begins at this page. When clicking on the "Authenticate with Java Web Start (new method)" link, a .jnlp file is downloaded, initiating a Java pr ...

Transforming data into a flat JSON format using jq

Currently, I am dealing with JSON data that needs to be inserted into a SQL database. This particular data is sourced from Google Cloud Firestore. Here is the input: { "0": { "filed1": "xxxx", "field": "zzzz" }, "1": { "field1": "xxx", ...

Implementing a Beveled Edge on a Shape using ThreeJS

I have put in a lot of effort to find the solution, but unfortunately I have not been successful so far. Currently, I am working on creating a shape using THREE.Shape, and I have the vertices data stored in a file. The shape appears to be straight without ...

Exploring the functionalities of MongoDB through Populate, Aggregate, and Un

My user model contains the following data structure: { _id: object, name: string, quotes: [ { quote: string, createdAt: date } ], friends: [ { _id: object } ] (referring to the _id from the user model) } My goal is to extract and return the following ...

Following the reconnection in Chrome, the onmessage() function does not trigger right away, even though a message has been received from the server

I am currently in the process of setting up a websocket connection between Chrome and a NodeJS server. The Node server is utilizing the ws plugin, while I am using Chrome's default websocket handler. Below are the snippets of code for the server: ws ...

What is the best method for accessing data values from HTML within a JavaScript function?

Greetings, I am relatively new to using jquery and ajax. Here is a snippet of my code: .html <li class="list-group-item"> <h2>Vocabulary</h2> <h4> <span class="label label-success">Like Name</span& ...

How can I include inline CSS directly within a string instead of using an object?

Is there a way to write inline CSS in a string format instead of an object format? I attempted the following, but it did not work as expected: <div style={"color:red;font-weight:bold"}> Hello there </div> What is my reason for want ...

ReactJS and Node -- The dreaded 400 bad request error strike again!

In my quest to create a react application that can store data in a database, I have come across some challenges. Here's the setup: server.js let express = require('express'); let bodyParser = require('body-parser'); let morgan = r ...