【发布时间】:2022-08-04 18:37:53
【问题描述】:
我有一些 XML 我想输入到 api 端点,但是,我需要将 xml 转换为 json 有效字符串才能这样做。当我在线搜索将 xml 转换为 JSON 或“JSON 有效字符串”时,我发现解析器将 xml 转换为与 xml 具有相同结构的 json 对象。我想要一些不同的东西,我想将 xml 转换为一个字符串,该字符串将用作 json 字典中的单个值。
这意味着我需要将新行转换为 \"\\n\"。结果还需要通过 JSON lint 验证。 https://jsonlint.com。
例如,假设我有以下快速代码:
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\"}
这是我需要转换为单行有效 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。
我怀疑我不是第一个做这种事情的人,所以我希望有人知道将 xml 转换为有效 json 字符串的公式。请帮忙。谢谢你。
-
您能否澄清“它破坏了 JSON linter”是什么意思? linter 会产生错误吗?如果是这样,它是什么错误?
-
在 JSON 字符串中,除了换行符之外,还有更多字符需要转义。
-
jq -cn --rawfile xml foo.xml \'$xml\'如果 jq 适用于您的环境。 -
@VadimBelyaev,我更新了提示。
-
对此没有“公式”,因为有数百种将 XML 转换为 JSON 的方法,所有这些最终都以不同的方式表示相同的信息。如果您从特定的 XML 格式开始并想要生成特定的 JSON 格式,那么您通常需要“手动”编写一些转换逻辑 - 通常 XSLT 3.0 可以是一个方便的工具。