如何将xml转换为有效的json字符串

How to convert xml to valid json string

提问人:ScottyBlades 提问时间:5/23/2022 最后编辑:ScottyBlades 更新时间:8/4/2022 访问量:124

问:

我有一些XML我想输入到api端点,但是,我需要将xml转换为json有效字符串才能这样做。当我在网上搜索将xml转换为JSON或“JSON有效字符串”时,我发现解析器可以将xml转换为与xml具有相同结构的json对象。我想要一些不同的东西,我想将xml转换为一个字符串,该字符串将用作json字典中的单个值。

这意味着我需要将新行转换为“\n”。此外,结果需要通过 JSON lint 验证。https://jsonlint.com

例如,假设我有以下 swift 代码:

import UIKit
import TableMVVM

class SubMenuChoice: NibView, HasViewModel {

    @IBOutlet var titleLabel: UILabel!
    @IBOutlet var detailsLabel: UILabel!
    @IBOutlet var viewToGradient: BottomLeftToTopRightGradient!

    var viewModel: ViewModel = .fallBack {
        didSet {
            self.titleLabel.text = viewModel.titleText
            self.detailsLabel.text = viewModel.detailText
            self.viewToGradient.layer.cornerRadius = 16
            self.viewToGradient.clipsToBounds = true
            self.viewToGradient.layer.borderColor = UIColor.white.cgColor
            self.viewToGradient.layer.borderWidth = 0.2
        }
    }
}

然后,我通过换掉文本回车符的新行,将其转换为有效的一行 json 字符串。

{"MyJSON" : "import UIKit\nimport TableMVVM\n\nclass SubMenuChoice: NibView, HasViewModel {\n\n    @IBOutlet var titleLabel: UILabel!\n    @IBOutlet var detailsLabel: UILabel!\n    @IBOutlet var viewToGradient: BottomLeftToTopRightGradient!\n\n    var viewModel: ViewModel = .fallBack {\n        didSet {\n            self.titleLabel.text = viewModel.titleText\n            self.detailsLabel.text = viewModel.detailText\n            self.viewToGradient.layer.cornerRadius = 16\n            self.viewToGradient.clipsToBounds = true\n            self.viewToGradient.layer.borderColor = UIColor.white.cgColor\n            self.viewToGradient.layer.borderWidth = 0.2\n        }\n    }\n}\n"}

enter image description here

这是我需要转换为单行的文本,有效的 json 字符串值:

import UIKit
import TableMVVM

class SubMenuChoice: NibView, HasViewModel {

    @IBOutlet var titleLabel: UILabel!
    @IBOutlet var detailsLabel: UILabel!
    @IBOutlet var viewToGradient: BottomLeftToTopRightGradient!

    var viewModel: ViewModel = .fallBack {
        didSet {
            self.titleLabel.text = viewModel.titleText
            self.detailsLabel.text = viewModel.detailText
            self.viewToGradient.layer.cornerRadius = 16
            self.viewToGradient.clipsToBounds = true
            self.viewToGradient.layer.borderColor = UIColor.white.cgColor
            self.viewToGradient.layer.borderWidth = 0.2
        }
    }
}

extension SubMenuChoice {
    struct ViewModel: HasFallBack {
        let titleText: String
        let detailText: String

        static var fallBack: Self {
            .init(titleText: "-", detailText: "-")
        }
    }
}

///// Interface builder XML, .xib  /////
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="19529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
    <device id="retina6_1" orientation="portrait" appearance="light"/>
    <dependencies>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/>
        <capability name="Image references" minToolsVersion="12.0"/>
        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
    </dependencies>
    <customFonts key="customFonts">
        <array key="Inter-Regular.ttf">
            <string>Inter-Regular</string>
        </array>
    </customFonts>
    <objects>
        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="SubMenuChoice" customModule="QRCodeTarot" customModuleProvider="target">
            <connections>
                <outlet property="detailsLabel" destination="cA5-NT-4u9" id="g9z-Bi-iPU"/>
                <outlet property="titleLabel" destination="Apr-Ou-WfJ" id="cAU-7I-Tk1"/>
                <outlet property="viewToGradient" destination="UG4-zb-Meg" id="cPu-gS-ndd"/>
            </connections>
        </placeholder>
        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
        <view contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="iN0-l3-epB">
            <rect key="frame" x="0.0" y="0.0" width="409" height="127"/>
            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
            <subviews>
                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="UG4-zb-Meg" customClass="BottomLeftToTopRightGradient" customModule="QRCodeTarot" customModuleProvider="target">
                    <rect key="frame" x="8" y="8" width="393" height="111"/>
                    <subviews>
                        <stackView opaque="NO" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" alignment="center" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="yCu-Vd-yGa">
                            <rect key="frame" x="20" y="20" width="353" height="71"/>
                            <subviews>
                                <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" alignment="top" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="IbF-c7-i6X">
                                    <rect key="frame" x="0.0" y="12" width="323" height="47.5"/>
                                    <subviews>
                                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Game 1" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Apr-Ou-WfJ">
                                            <rect key="frame" x="0.0" y="0.0" width="60" height="21"/>
                                            <fontDescription key="fontDescription" name="Inter-Regular" family="Inter" pointSize="17"/>
                                            <color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                                            <nil key="highlightedColor"/>
                                        </label>
                                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Short Description of game. " textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="cA5-NT-4u9">
                                            <rect key="frame" x="0.0" y="29" width="194.5" height="18.5"/>
                                            <fontDescription key="fontDescription" name="Inter-Regular" family="Inter" pointSize="15"/>
                                            <color key="textColor" red="0.70196078431372544" green="0.70196078431372544" blue="0.70196078431372544" alpha="1" colorSpace="calibratedRGB"/>
                                            <nil key="highlightedColor"/>
                                        </label>
                                    </subviews>
                                </stackView>
                                <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="fmD-Uj-nrG">
                                    <rect key="frame" x="331" y="25.5" width="22" height="20"/>
                                    <color key="tintColor" red="0.70196563010000002" green="0.70195221900000004" blue="0.70196127890000004" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
                                    <constraints>
                                        <constraint firstAttribute="width" constant="22" id="5nL-F4-TDg"/>
                                        <constraint firstAttribute="width" secondItem="fmD-Uj-nrG" secondAttribute="height" id="TJa-x2-MQi"/>
                                        <constraint firstAttribute="height" constant="22" id="zxE-9d-IP3"/>
                                    </constraints>
                                    <imageReference key="image" image="chevron.right" catalog="system" symbolScale="default"/>
                                    <preferredSymbolConfiguration key="preferredSymbolConfiguration" scale="default" weight="semibold"/>
                                </imageView>
                            </subviews>
                        </stackView>
                    </subviews>
                    <color key="backgroundColor" red="0.094216383989999999" green="0.097880952059999998" blue="0.1137293801" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
                    <accessibility key="accessibilityConfiguration" hint="GradientRoundedbox" identifier="GradientRoundedbox" label="GradientRoundedbox">
                        <bool key="isElement" value="NO"/>
                    </accessibility>
                    <constraints>
                        <constraint firstItem="yCu-Vd-yGa" firstAttribute="top" secondItem="UG4-zb-Meg" secondAttribute="top" constant="20" id="3RX-6j-jOS"/>
                        <constraint firstAttribute="trailing" secondItem="yCu-Vd-yGa" secondAttribute="trailing" constant="20" id="EO3-94-kqy"/>
                        <constraint firstItem="yCu-Vd-yGa" firstAttribute="leading" secondItem="UG4-zb-Meg" secondAttribute="leading" constant="20" id="ZqU-CK-TE2"/>
                        <constraint firstAttribute="bottom" secondItem="yCu-Vd-yGa" secondAttribute="bottom" constant="20" id="j7q-UD-Mtj"/>
                    </constraints>
                </view>
            </subviews>
            <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
            <constraints>
                <constraint firstAttribute="trailing" secondItem="UG4-zb-Meg" secondAttribute="trailing" constant="8" id="2oh-y3-hqC"/>
                <constraint firstItem="UG4-zb-Meg" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="8" id="97v-Yx-mRr"/>
                <constraint firstItem="UG4-zb-Meg" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" constant="8" id="eJq-NG-K3S"/>
                <constraint firstAttribute="bottom" secondItem="UG4-zb-Meg" secondAttribute="bottom" constant="8" id="yw9-bW-Zza"/>
            </constraints>
            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
            <point key="canvasLocation" x="128.2608695652174" y="-143.63839285714286"/>
        </view>
    </objects>
    <resources>
        <image name="chevron.right" catalog="system" width="96" height="128"/>
    </resources>
</document>


///// Unit tests  /////

Import XCTest

class SubMenuChoiceTests: XCTestCase { 
    
    
}

当我尝试用新的行文字交换新行时,它会破坏 JSON linter。

enter image description here

我怀疑我不是第一个做这种事情的人,所以我希望有人知道将 xml 转换为有效 json 字符串的公式。请帮忙。谢谢。

iOS JSON XML Bash 解析

评论

0赞 Vadim Belyaev 5/23/2022
请您澄清一下“it breaks the JSON linter”是什么意思?linter 是否会产生错误?如果是这样,它是什么错误?
0赞 Shawn 5/23/2022
除了换行符之外,还有更多字符必须在 JSON 字符串中转义。
0赞 Shawn 5/23/2022
jq -cn --rawfile xml foo.xml '$xml'如果 JQ 可用于您的环境。
1赞 Michael Kay 5/23/2022
这没有“公式”,因为有数百种方法可以将XML转换为JSON,所有这些方法最终都以不同的方式表示相同的信息。如果您从特定的 XML 格式开始,并且想要生成特定的 JSON 格式,那么您通常需要“手动”编写一些转换逻辑 - 通常 XSLT 3.0 可以是一个方便的工具。
0赞 ScottyBlades 5/24/2022
我想我主要会自己写。

答:

1赞 mike.f 8/4/2022 #1

您可以使用 github.com/mikefarah/yq 执行此操作

yq -n --indent=0 '.MyJson = load_str("file.txt")' -o=json

这将创建一个新的 JSON 文档,其中包含字符串内容。它会自动转义字符。

免责声明:我写了yq

评论

0赞 ScottyBlades 8/5/2022
凉。当我回到这个项目时,我会试一试。谢谢。