* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { JsonPrimitive } from '../../jsonPrimitive';
import { JsonArray } from '../../jsonArray';
import { JsonObject } from '../../jsonObject';
import { StringBuilder } from '../../lang/stringBuilder';
import { JsonNull } from '../../jsonNull';
import { JsonWriter } from '../../stream/jsonWriter'
import { JsonElement } from '../../jsonElement'
const UNWRITABLE_WRITER: StringBuilder = new StringBuilder();
const SENTINEL_CLOSED: JsonPrimitive = new JsonPrimitive("closed");
export class JsonTreeWriter extends JsonWriter {
private _stack: Array<JsonElement> = new Array();
private pendingName: string;
private product: JsonElement = JsonNull.INSTANCE;
constructor() {
super(UNWRITABLE_WRITER)
}
public get(): JsonElement {
if (this._stack.length !== 0) {
throw new Error("Expected one JSON element but was " + this._stack);
}
return this.product;
}
private _peek(): JsonElement {
return this._stack[this._stack.length - 1];
}
private put(value: JsonElement): void {
if (this.pendingName !== null && this.pendingName !== undefined) {
if (value instanceof JsonNull === false || super.getSerializeNulls()) {
let object: JsonObject = this._peek() as JsonObject;
object.add(this.pendingName, value);
}
this.pendingName = null;
} else if (this._stack.length === 0) {
this.product = value;
} else {
let element: JsonElement = this._peek();
if (element instanceof JsonArray) {
element.add(value);
} else {
throw new Error('IllegalStateException');
}
}
}
public beginArray(): JsonWriter {
let array: JsonArray = new JsonArray();
this.put(array);
this._stack.push(array);
return this;
}
public endArray(): JsonWriter {
if (this._stack.length === 0 || this.pendingName != null) {
throw new Error('IllegalStateException');
}
let element: JsonElement = this._peek();
if (element instanceof JsonArray) {
this._stack.pop();
return this;
}
throw new Error('IllegalStateException');
}
public beginObject(): JsonWriter {
let object: JsonObject = new JsonObject();
this.put(object);
this._stack.push(object);
return this;
}
public endObject(): JsonWriter {
if (this._stack.length === 0 || this.pendingName != null) {
throw new Error('IllegalStateException');
}
let element: JsonElement = this._peek();
if (element instanceof JsonObject) {
this._stack.pop();
return this;
}
throw new Error('IllegalStateException');
}
public name(_name: string): JsonWriter {
if (_name === null || _name === undefined) {
throw new Error('name == null');
}
if (this._stack.length === 0 || this.pendingName != null) {
throw new Error('IllegalStateException');
}
let element: JsonElement = this._peek();
if (element instanceof JsonObject) {
this.pendingName = _name;
return this;
}
}
public value(_value: string | number | boolean): JsonWriter {
if (_value === null || _value === undefined) {
return this.nullValue();
}
if (!this.isLenient() && typeof _value === 'number') {
if (Number.isNaN(_value) || !Number.isFinite(_value)) {
throw new Error('IllegalStateException');
}
}
this.put(new JsonPrimitive(_value));
return this;
}
public nullValue(): JsonWriter {
this.put(JsonNull.INSTANCE);
return this;
}
public close(): void {
if (this._stack.length !== 0) {
throw new Error("Incomplete document");
}
this._stack.push(SENTINEL_CLOSED);
}
}